处理服务或 DAO 中的聚合

Posted

技术标签:

【中文标题】处理服务或 DAO 中的聚合【英文标题】:Handling Aggregations in a Service or DAO 【发布时间】:2012-01-10 06:21:33 【问题描述】:

关于设计合适的 DAO 的热门讨论总是以“DAO 应该只执行简单的 CRUD 操作”的方式结束。

那么执行聚合等操作的最佳位置是什么? DAO 是否应该返回类似于您的数据源架构的复杂对象图?

假设我有以下 DAO 接口:

public interface UserDao 
    public User getByName(String name);

这里是它返回的对象:

public class Transaction 
    public int amount;
    public Date transactionDate;


public class User 
    public String name;
    public Transaction[] transactions;

首先,如果 DAO 所做的只是 CRUD 操作,我认为它会返回一个标准值对象。

所以现在我已经通过 DAO 建模,以基于数据存储关系返回一些东西。它是否正确?如果我有一个更复杂的对象图怎么办?

更新:我想我在这部分要问的是,DAO 的返回值,无论是 VO、DTO 还是你想调用的任何东西,都应该以数据为模型商店的数据表示?或者我应该引入一个新的 DAO 来获取用户的交易,并且对于被 UserDAO 拉取的每个用户,调用对 TransactionDAO 的调用来获取它们?

其次,假设我想对用户的所有交易执行聚合。使用这个 DAO,我可以简单地获取一个用户,并在我的服务循环中通过 transactions 数组并自己执行聚合。毕竟,完全可以说这样的聚合是属于 Service 的业务规则。

但是,如果用户的交易数量达到数万怎么办。这将对应用程序性能产生负面影响。在 DAO 上引入一种新方法来进行上述聚合是否不正确?

当然,这可能假设 DAO 由数据库备份,我可以在其中编写简单的 SELECT SUM() 查询。如果 DAO 实现更改为平面文件或其他内容,我无论如何都需要在内存中进行聚合。

那么这里的最佳做法是什么?

【问题讨论】:

【参考方案1】:

我使用 DAO 作为翻译层:读取 db 对象,创建 java 端业务对象,反之亦然。有时,可能会使用几个调用来存储或创建业务对象。对于提供的示例,我会进行两次调用:一次调用用户信息,一次调用用户交易列表。代价是额外的数据库调用。如果我使用连接池并且我不重复计算,我不怕打额外的电话。单独的调用更易于使用(从 jdbc 调用中解包复合类型数组并不简单,通常需要专有的连接对象)并提供可重用的组件。假设您想要登录屏幕的用户对象:您可以使用相同的用户 dao 而不必拉入交易内容。

如果您实际上并不想要事务详细信息,而只是对聚合感兴趣,我会在数据库端进行聚合工作并通过视图或存储过程公开它。关系数据库是为这些类型的集合操作而构建并擅长的。您不太可能更好地执行操作。此外,如果结果可行,则通过线路发送所有数据是没有意义的。当然,如果您有时只对此感兴趣,请为聚合添加另一个 dao。

假设 dao 映射到关系数据库是否安全?如果这就是您开始的方式,我敢打赌后备数据存储将仍然是关系数据库。有时要保持通用性会大惊小怪,如果可以的话,那就太好了。但在我看来,只是在后面更改关系数据库的类型比大多数应用程序都走得更远(更不用说更改为像平面文件这样的非关系存储了)。

【讨论】:

以上是关于处理服务或 DAO 中的聚合的主要内容,如果未能解决你的问题,请参考以下文章

简单工厂 (UML) 中的聚合或依赖

“聚合支付”增值盛宴:打通银行垂直账户壁垒

聚合支付系统开发,聚合支付引领支付科技

聚合支付的发展之路,锋锐聚合支付系统开发

聚合支付的发展之路,锋锐聚合支付系统开发

如何修复where子句中的聚合?