【问题标题】:Handling Aggregations in a Service or DAO处理服务或 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 实现更改为平面文件或其他内容,我无论如何都需要在内存中进行聚合。

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

【问题讨论】:

    标签: java design-patterns dao dto


    【解决方案1】:

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

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

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

    【讨论】:

      猜你喜欢
      • 2013-04-13
      • 1970-01-01
      • 1970-01-01
      • 2020-01-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多