Java EE Architecture - 在使用像JPA 2这样的ORM时,DAO是否仍然被推荐?

2022-08-31 23:41:25

如果我使用的是像 JPA2 这样的 ORM - 其中我的实体映射到我的数据库,我是否仍应使用 DAO?这似乎需要更多的开销。

例如,我需要维护三个额外的包:

  1. 一个指定我的域对象(它几乎映射我的实体对象):

    public class Employee {
        private String firstName;
        private String lastName;
        ...
        // Getters and setters
    }
    
  2. 一个包含指定我的DAO方法的接口

    public interface EmployeeDAO {
        public void addEmployee(Employee employee);
        public Employee getEmployeeById(long id);
        ...
    }
    
  3. 一个包含会话bean,用于实现我的DAO的

    public EmployeeJpaDAO implements EmployeeDAO {
        interface method implementations here
        ....
        private method that transform my Employee entity into my Employee domain object
    }
    

现在,每次我需要执行新的CRUD操作时,都需要添加很多额外的行李。

然而,我看到拥有DAO的好处是:

  1. 您可以使用 DAO 的内存实现来对服务层进行单元测试。这意味着您无需访问数据库来测试业务逻辑,并且可以放心,您的对象将始终包含相同的属性值。

  2. 它将业务逻辑与数据库访问逻辑分开

不涉及实现 DAO 的选项是只在服务层中使用实体对象和实体管理器:

@Stateless
public class EmployeeEjb {
    @PersistenceContext(unitName = "employee")
    private EntityManager manager;

    public Employee getEmployeeById(long id) {
        return manager.createNamedQuery(Employee.GetEmployeeById).getResultList();
    }
    ...
}

这里没有中间地带吗?有没有人遇到过一个架构或实现一个架构,它满足了我上面提到的DAO层的一些好处(最重要的是业务逻辑的单元可测试性),但不涉及实现DAO层所涉及的所有开销?

感谢您的任何建议和/或建议!我真的很好奇有些人对此有什么看法。


答案 1

如果我使用的是像 JPA2 这样的 ORM - 其中我的实体映射到我的数据库,我是否仍应使用 DAO?这似乎需要更多的开销。

是的。显然,Java EE并不鼓励在使用JPA时使用DAO模式(JPA已经提供了域存储模式的标准化实现,并且在DAO后面屏蔽它没有太多价值)。在这种情况下,我发现DAO是反DRY的。

因此,对于简单的情况(实际上,大多数情况),我很乐意跳过DAO,我对此没有问题。对于更复杂的情况(例如,使用存储过程、平面文件时),我会使用它。换句话说,这取决于,正如JPA杀死DAO吗?另请参阅下面的相关问题:

相关问题

(...)一个包含会话bean,用于实现我的DAO的

不,您当然不想将 DAO 实现为会话 Bean:

  • 您不想创建与表一样多的(池化)会话 Bean(大量浪费资源)
  • 您不想将会话Bean链接在任何地方,不要重现过去的错误,这是一种已知的不良做法,不能很好地扩展。

因此,如果你真的想走DAO的方式并希望注入EM,要么将你的DAO实现为Spring bean(在Java EE 5中)或CDI托管bean(在Java EE 6中)。

您可以使用 DAO 的内存实现来对服务层进行单元测试。

如果你真的想做单元测试,模拟DAO/EntityManager,没有区别。如果要进行集成测试,可以将 JPA 配置为使用内存中的数据库。所以最后,我只是不相信这个论点。

它将业务逻辑与数据库访问逻辑分开

老实说,我不认为依赖DAO和实体经理之间有很大的区别,我不明白DAO如何“更好地”分离事物。再说一遍,我不相信这个论点。

根据我的经验,改变底层持久性解决方案是一个非常特殊的事件,我不打算为很可能不会发生的事情(YAGNIKISS)引入DAO。

这里没有中间地带吗?有没有人遇到过一个架构或实现一个架构,它满足了我上面提到的DAO层的一些好处(最重要的是业务逻辑的单元可测试性),但不涉及实现DAO层所涉及的所有开销?

我没有看到太多的中间立场,正如强烈暗示的那样,如果我觉得没有必要,我就不会使用DAO。正如我所说,如果你想真正对业务逻辑进行单元测试,那就模拟它。它适用于我,我很乐意编写更少的代码。EntityManager

更多资源


答案 2

记录在案。

对于单一责任原则(SRP),DAO是必须的,它将模型和逻辑分离在一个持久性层中,该持久层可以轻松移植。

如果一个项目正在使用测试单元,那么DAO可以帮助正确测试它(模型,数据库测试等)。

DAO是一个服务,就像一个服务一样,我们可以将我们的流程包装在一个易于维护的漂亮类中。

JPA减少了代码行数,但仅此而已,旧规则仍然适用。

JPA带来了一个存储库层,但它不是我们的存储库层。在相同的原理中,假设我们封装了一个获得某些过程利润的逻辑。也许封装只是0.1的乘法,但它仍然值得封装。

例如,假设我有下一个问题:由于某种奇怪的原因,我可以在数据库中插入一个新的客户端?我应该从哪里开始测试?a:如果存在,如果不存在,那么祝你好运,在其他地方找到。


推荐