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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3818589/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 05:26:24  来源:igfitidea点击:

Java EE Architecture - Are DAO's still recommended when using an ORM like JPA 2?

javajakarta-eedaojpa-2.0architecture

提问by Brian DiCasa

If I'm using an ORM like JPA2 - where I have my entities that are mapped to my database, should I still be using a DAO? It seems like a lot more overhead.

如果我使用的是像 JPA2 这样的 ORM - 我的实体映射到我的数据库,我还应该使用 DAO 吗?这似乎是更多的开销。

For example, I would need to maintain three extra packages:

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

  1. One that specifies my domain objects (which pretty much map my Entity objects):

    public class Employee {
        private String firstName;
        private String lastName;
        ...
        // Getters and setters
    }
    
  2. One that contains interfaces that specify my DAO methods

    public interface EmployeeDAO {
        public void addEmployee(Employee employee);
        public Employee getEmployeeById(long id);
        ...
    }
    
  3. One that contains session beans that implement my DAO's

    public EmployeeJpaDAO implements EmployeeDAO {
        interface method implementations here
        ....
        private method that transform my Employee entity into my Employee domain object
    }
    
  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. 一个包含实现我的 DAO 的会话 bean

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

Now that's a lot of extra baggage to add every time I need to perform a new CRUD operation.

现在,每次我需要执行新的 CRUD 操作时,都会增加很多额外的负担。

However the benefits I see from having a DAO is:

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

  1. You can have an in memory implementation of the DAO for unit testing your service layer. This means you don't need to access the database to test business logic, and you can be assured that your objects will always contain the same values for properties

  2. It separates business logic from database access logic

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

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

The option that doesn't involve implementing a DAO is to just use entity objects and EntityManager in the service layer:

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

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

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

Is there no middle ground here? Has anyone come across an architecture or implemented an architecture that meets some of the benefits of a DAO layer (most importantly the unit testability of business logic) that I mentioned above, but doesn't involve all the overhead involved to implement a DAO layer?

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

Thanks for any recommendations and/or suggestions! I'm really curious to see what some people have come up with in regards to this.

感谢您的任何建议和/或建议!我真的很想知道有些人对此有何看法。

采纳答案by Pascal Thivent

If I'm using an ORM like JPA2 - where I have my entities that are mapped to my database, should I still be using a DAO? It seems like a lot more overhead.

如果我使用的是像 JPA2 这样的 ORM - 我的实体映射到我的数据库,我还应该使用 DAO 吗?这似乎是更多的开销。

It is. And clearly, Java EE doesn't encourage using the DAOpattern when using JPA (JPA already provides a standardized implementation of the Domain Storepattern and there isn't much value at shielding it behind a DAO). I find the DAO to be anti-DRYin such situation.

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

So for simplecases (actually, most cases), I happily skip the DAO and I have no problem with that. For more complexcases (for example when using stored procedures, flat files), I'd use it. In other words, it depends, as summarized in Has JPA Killed the DAO?. See also the related questions below:

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

Related questions

相关问题

(...) One that contains session beans that implement my DAO's

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

Noooo, you certainly don't want to implement a DAO as a Session Bean:

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

  • You don't want to create as much (pooled) Session Bean as tables (big waste of resources)
  • You don't want to chain Session Beans everywhere, don't reproduce errors from the past, this is a known bad practice that doesn't scale well.
  • 您不想创建与表一样多的(池化)会话 Bean(资源浪费很大)
  • 您不想将 Session Bean 链接到任何地方,也不想重现过去的错误,这是众所周知的不好扩展的做法。

So if you really want to go the DAO way and want the EM to be injected, either implement your DAOs as Spring beans (in Java EE 5) or CDI managed bean (in Java EE 6).

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

You can have an in memory implementation of the DAO for unit testing your service layer.

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

If you really want to do unittesting, mock the DAO/EntityManager, there is no difference. And if you want to do integration testing, you can configure JPA to use an in memory database. So at the end, I just don't buy this argument.

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

It separates business logic from database access logic

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

Honestly, I don't see a bigdifference between relying on a DAO vs an entity manager, I don't see how a DAO separate things "better". Again, I don't buy this argument.

老实说,我没有看到依赖 DAO 和实体管理器之间的区别,我看不到 DAO 如何“更好地”分离事物。再说一次,我不买这个论点。

And to my experience, changing the underlying persistence solution is a very exceptional event and I'm not going to introduce DAOs for something that is very likely not going to happen (YAGNI, KISS).

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

Is there no middle ground here? Has anyone come across an architecture or implemented an architecture that meets some of the benefits of a DAO layer (most importantly the unit testability of business logic) that I mentioned above, but doesn't involve all the overhead involved to implement a DAO layer?

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

I don't see much middle ground and, as strongly hinted, I don't use DAOs if I don't feel the need. And as I said, mock the EntityManagerif you want to truly unit test the business logic. It works for me and I'm happy to write less code.

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

More resources

更多资源

回答by magallanes

For the record.

作为记录。

For Single responsibility principle (SRP), DAO is a must have, it separates the model and logic in a persistence layer that can be easily portable.

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

If a project is using Test Unit then DAO helps to test it correctly (mockup, database testing and so on).

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

DAO is a SERVICE and like one, we could wrap our process in a nicely class that is easy to maintenance.

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

JPA reduces the number of lines of codes but, nothing more, the old rules still applies.

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

JPA brings a repository layer but its not OUR repository layer. In the same principle, let's say that we encapsulated a logic that obtain the profit of some process. May be the encapsulation is simply a multiplication for 0.1 but its still worthy to encapsulate.

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

For example, let's say that i have the next problem : for some odd reason, i can insert a new Client in the database?. Where should i start to test?. a: ClientDao if exists, if not, then good luck finding elsewhere.

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