处理服务或DAO中的聚合

时间:2011-12-01 02:03:36

标签: java design-patterns dao dto

关于设计适当的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返回一个标准的Value Object,如果它只是CRUD操作。

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

更新:我想我在这部分要问的是,如果DAO的返回值,无论是VO,DTO还是其他任何你想要调用它的,都应该在数据之后建模商店的数据表示?或者我应该介绍一个新的DAO以获取用户的交易,并且对于UserDAO提取的每个用户,调用TransactionDAO来调用它们?

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

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

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

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

1 个答案:

答案 0 :(得分:0)

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

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

假设dao映射到关系数据库是否安全?如果这是你的开始,我会打赌后备数据存储将保持关系数据库。有时会有很多大惊小怪和担心保持通用,如果可以的话,很棒。但在我看来,只是在后面更改关系数据库的类型比大多数应用程序更进一步(更不用说改为像平面文件这样的非关系存储)。