3

我有一个包含以下 java 文件的应用程序:

服务:

AccountService.java
UserService.java
MessageService.java

DAO:

AccountDAO.java
UserDAO.java
MessageDAO.java

表:

ACCOUNTS
USERS
MESSAGES

MessageService.java中,我有一个newMessage()必须从所有 3 个表中查询数据的函数。

(1) 根据 Spring 的解耦标准,应该这样调用:

                     AccountDAO.java -- ACCOUNTS
                    /
MessageService.java -- MessageDAO.java -- MESSAGES
                    \
                     UserDAO.java -- USERS

但问题是,这种方法会进行 3 次 DB 调用。

(2) 为了获得更好的性能,我会这样做:

MessageService.java -- MessageDAO.java -- Join ACCOUNTS, MESSAGES and USERS

但是这样,它是紧密耦合的,如果 USERS 表发生变化,我将不得不更改 MessageDAO.java(以及我拥有的所有其他使用 USERS 表的 DAO)。这真的很糟糕,因为(在非假设的情况下)我们有很多 DAO

哪种方法被认为是更好的做法?还是我缺少另一种方法?

4

4 回答 4

4

根据 Spring 的解耦标准,这就是调用的方式

这是错误的。Spring 没有“解耦标准”。请在 Spring 文档中找到我的参考资料,该参考资料告诉您必须如何构建持久层代码。

通常,您的应用程序要操作的每个“实体”都有一个 DAO,但是如果将这种模式发挥到极致,即解构将多个表连接成三个不同查询的查询,那将是愚蠢的。

如果您需要一种newMessage()在查询中将一些表连接在一起的方法,请选择最有意义的 DAO - 可能MessageDAO并以有意义的方式编写查询/方法。

但是没有规定必须对每个实体有不同的查询,并且不允许一个 DAO 类进行涉及其他实体表的查询。这太极端了,没有任何好处。

另一方面,如果您担心拥有多个知道所有表的数据层类的可维护性,那么请研究 Parsifal 提到的 ORM 解决方案以减轻其中的一些工作。

于 2012-10-10T20:34:01.163 回答
4

另一种方法是使用诸如 Hibernate 之类的 ORM,将每个表映射到一个实体。然后定义这些实体之间的逻辑关系。例如,用户和消息之间的 1:M 关系。当你的表改变时,你的映射需要改变,但你的 SQL 不会改变(因为 Hibernate 会生成它)。

对于大多数关系,Hibernate 非常擅长创建连接以在一个查询中检索相关实体。您可以控制是否发生这种情况;我建议使用延迟加载作为大多数关系的默认值,并根据需要切换到急切加载。

于 2012-10-10T20:55:00.040 回答
2

如果数据可能在一个查询和下一个查询之间发生变化,那么作为 3 个单独的查询执行此操作可能会影响正确性。不要让(你的想法)Spring 的指导方针让你编写得到错误结果的代码。

听起来 SQL 中的连接是正确的方法。

于 2012-10-10T20:59:28.980 回答
1

无论您采用哪种方法,它始终是在解耦和性能之间找到一个最佳点。它甚至适用于层数的选择等。

所以我想正如@mattb 推荐的那样,如果在特定上下文中有意义,那么在 DAO 中加入表是完全可以的

于 2012-10-12T11:18:57.180 回答