JavaEE体系结构——Are DAO';当使用像JPA2这样的ORM时,仍然建议使用什么?

JavaEE体系结构——Are DAO';当使用像JPA2这样的ORM时,仍然建议使用什么?,java,jakarta-ee,dao,jpa-2.0,architecture,Java,Jakarta Ee,Dao,Jpa 2.0,Architecture,如果我使用的是像JPA2这样的ORM,我的实体映射到我的数据库,那么我还应该使用DAO吗?看起来开销要大得多 例如,我需要维护三个额外的包: 一个指定我的域对象(它几乎映射了我的实体对象): 一个包含指定我的DAO方法的接口 public interface EmployeeDAO { public void addEmployee(Employee employee); public Employee getEmployeeById(long id); ... }

如果我使用的是像JPA2这样的ORM,我的实体映射到我的数据库,那么我还应该使用DAO吗?看起来开销要大得多

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

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

  • 一个包含指定我的DAO方法的接口

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

    public EmployeeJpaDAO implements EmployeeDAO {
        interface method implementations here
        ....
        private method that transform my Employee entity into my Employee domain object
    }
    
  • 现在,每当我需要执行一个新的CRUD操作时,都需要添加很多额外的行李

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

  • 您可以在内存中实现DAO,以便对服务层进行单元测试。这意味着您不需要访问数据库来测试业务逻辑,并且可以确保您的对象始终包含相同的属性值

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

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

    @Stateless
    public class EmployeeEjb {
        @PersistenceContext(unitName = "employee")
        private EntityManager manager;
    
        public Employee getEmployeeById(long id) {
            return manager.createNamedQuery(Employee.GetEmployeeById).getResultList();
        }
        ...
    }
    
    这里没有中间立场吗?有没有人遇到过一个体系结构或实现了一个体系结构,该体系结构满足了我上面提到的DAO层的一些好处(最重要的是业务逻辑的单元可测试性),但不涉及实现DAO层所涉及的所有开销

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

    如果我使用的是像JPA2这样的ORM,我的实体映射到我的数据库,那么我还应该使用DAO吗?看起来开销要大得多

    是的。显然,JavaEE不鼓励在使用JPA时使用该模式(JPA已经提供了该模式的标准化实现,在DAO后面屏蔽它没有多大价值)。我发现在这种情况下刀是反的

    所以对于简单的案例(实际上,大多数案例),我很乐意跳过DAO,我对此没有问题。对于更复杂的情况(例如使用存储过程、平面文件时),我会使用它。换句话说,这取决于,如中所总结的。另见以下相关问题:

    相关问题
    (…)包含实现我的DAO的会话bean的一个

    public EmployeeJpaDAO implements EmployeeDAO {
        interface method implementations here
        ....
        private method that transform my Employee entity into my Employee domain object
    }
    
    Noooo,您当然不想将DAO实现为会话Bean:

    • 您不希望创建与表一样多的(池)会话Bean(极大地浪费资源)
    • 您不希望将会话bean链接到任何地方,也不希望重现过去的错误,这是一种已知的不好的做法,不能很好地扩展
    因此,如果您真的想走DAO的道路并希望注入EM,那么可以将DAO实现为Springbean(在JavaEE5中)或CDI管理的bean(在JavaEE6中)

    您可以在内存中实现DAO,以便对服务层进行单元测试

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

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

    老实说,我不认为依赖DAO和实体管理器之间有什么区别,我不认为DAO如何将事情“更好”地分开。再说一遍,我不相信这种说法

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

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

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

    更多资源
    记录在案

    对于单一责任原则(SRP),DAO是必须具备的,它将模型和逻辑分离在一个易于移植的持久层中

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

    DAO是一种服务,与之类似,我们可以将流程封装在一个易于维护的类中

    JPA减少了代码行数,但旧规则仍然适用

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


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

    谢谢你提供的信息性回复。我问了另外一个问题,如果您想了解一下,在使用带有DAO的JPA时,如何对EJB进行单元测试:D为什么将DAOs实现为SLSB是一种关于可伸缩性的糟糕做法?哪些问题与此相关,应用程序会以何种“规模”出现此类问题?我害怕在JavaEE环境中使用Spring,这也会重现过去的一个大错误…@Pascal我知道你的答案已经好几年了,