9ee*_*ee1 5 java dao design-patterns dto
关于设计合适的 DAO 的讨论总是如此流行,其结论总是“DAO 应该只执行简单的 CRUD 操作”。
那么执行聚合等操作的最佳位置是什么?DAO 是否应该返回类似于数据源架构的复杂对象图?
假设我有以下 DAO 接口:
public interface UserDao {
public User getByName(String name);
}
Run Code Online (Sandbox Code Playgroud)
这是它返回的对象:
public class Transaction {
public int amount;
public Date transactionDate;
}
public class User {
public String name;
public Transaction[] transactions;
}
Run Code Online (Sandbox Code Playgroud)
首先,我认为如果 DAO 所做的只是 CRUD 操作,那么它会返回一个标准值对象。
所以现在我已经通过 DAO 建模来返回基于数据存储关系的东西。它是否正确?如果我有更复杂的对象图怎么办?
更新:我想我在这一部分中要问的是,DAO 的返回值(无论是 VO、DTO 还是任何您想要的名称)是否应该按照数据存储的数据表示进行建模?或者我应该引入一个新的 DAO 来获取用户的交易,并为 UserDAO 拉取的每个用户调用 TransactionDAO 来获取它们?
其次,假设我想对用户的所有交易执行聚合。使用这个 DAO,我可以简单地获取一个用户,并在我的服务循环中遍历事务数组并自己执行聚合。毕竟,说这样的聚合是属于服务的业务规则是完全合理的。
但如果用户的交易数量达到数万怎么办?这会对应用程序性能产生负面影响。在 DAO 上引入一种执行上述聚合的新方法是否不正确?
当然,这可能是假设 DAO 由数据库备份,我可以在其中编写简单的 SELECT SUM() 查询。如果 DAO 实现更改为平面文件或其他内容,我无论如何都需要在内存中进行聚合。
那么这里的最佳实践是什么?
我使用 DAO 作为转换层:读取数据库对象,创建 java 端业务对象,反之亦然。有时,可能会使用几个调用来存储或创建业务对象。对于提供的示例,我将进行两次调用:一个用于用户信息,一个用于用户交易列表。代价是额外的数据库调用。如果我使用连接池并且不重复计算,我就不怕进行额外的调用。单独的调用使用起来更简单(从 jdbc 调用中解包复合类型数组并不简单,通常需要专有的连接对象)并提供可重用的组件。假设您想要用于登录屏幕的用户对象:您可以使用相同的用户 dao 而不必提取事务内容。
如果您实际上并不需要事务详细信息,而只是对聚合感兴趣,那么我将在数据库端进行聚合工作,并通过视图或存储过程公开它。关系数据库是为此类集合运算而构建的,并且擅长此类运算。您不太可能更好地执行操作。此外,如果结果可以的话,就没有必要通过网络发送所有数据。因此,如果有时您只对此感兴趣,请为聚合添加另一个 dao。
假设 dao 映射到关系数据库是否安全?如果这就是您开始的方式,我敢打赌支持数据存储将仍然是关系数据库。有时为了保持通用性需要很多麻烦和担忧,如果可以的话,那就太好了。但在我看来,仅仅更改后面的关系数据库的类型比大多数应用程序要走得更远(更不用说更改为平面文件等非关系存储)。