gpt4 book ai didi

hibernate - EntityManager 应该如何在一个很好的解耦的服务层和数据访问层中使用?

转载 作者:行者123 更新时间:2023-12-04 03:23:02 25 4
gpt4 key购买 nike

与我的其他问题有些相关 Should raw Hibernate annotated POJO's be returned from the Data Access Layer, or Interfaces instead? ,我在创建良好解耦的层方面经验丰富,但不使用 Hibernate 或 J2EE/JPA。我一直在查看文档和教程,对如何以优雅的方式使用 EntityManger 感到困惑,因为它似乎负责事务(我想在我的服务层执行)和持久性方法(我想要保存在数据访问层中)。我应该在服务层创建它并将其注入(inject)数据访问层,还是有更好的方法?下面的伪java大致显示了我正在考虑做的事情。

编辑:我下面的伪代码基本上取自 hibernate JPA 教程并针对层分离进行了修改,并不反射(reflect)正在开发该产品以在 EJB 容器(Glassfish)中运行。在您的答案中,请提供在 Glassfish 或等效程序中运行的代码的最佳实践和代码示例。

MyService
{

setup()
{
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory( "Something" ); //is the String you pass in important?
entityManager = entityManagerFactory.createEntityManager();
}

myServiceMethod()
{
entityManager.getTransaction().begin();
MyDao.setEntityManager(entityManagerFactory);
MyDao.doSomething();
MyDao.doSomethingElse();
entityManager.getTransaction().commit();
entityManager.close();
}
}

MyDao
{
doSomething()
{
entityManager.persist(...); //etc
}

}

最佳答案

首先,是否应该使用 DAO 层是自 JPA 和许多人认为是 DAO 本身的 EntityManager 出现以来一直存在的争论。这个问题的答案取决于您正在开发的应用程序的类型,但在大多数情况下,您会希望:

  • 使用 JPA 标准或自定义查询 .在这种情况下,您可能不想将业务逻辑与查询创建混合在一起。这将导致大型方法并违反 single responsibility principle .
  • 尽可能重用您的 JPA 代码 .假设您创建了一个条件查询,该查询检索年龄在 40 到 65 岁之间且在公司工作超过 10 年的员工列表。您可能希望在服务层的其他地方重用这种类型的查询,如果是这种情况,将它放在服务中会使这项任务变得困难。

  • 话虽这么说,如果您的应用程序中只有 CRUD 操作,并且您认为您可能不需要重用任何 JPA 代码,那么 DAO 层可能有点矫枉过正,因为它仅充当 EntityManager 的包装器,它不会听起来不对。

    其次,我建议尽可能使用容器管理的事务。如果您使用的是像 TomEE 或 JBoss 这样的 EJB 容器,这将避免大量专用于以编程方式创建和管理事务的代码。

    如果您使用的是 EJB 容器,则可以利用声明式事务管理。使用 DAO 的一个示例是将您的服务层组件创建为 EJB 和您的 DAO。
    @Stateless
    public class CustomerService {

    @EJB
    CustomerDao customerDao;

    public Long save(Customer customer) {

    // Business logic here
    return customerDao.save(customer);
    }
    }

    @Stateless
    public class CustomerDao {

    @PersistenceContext(unitName = "unit")
    EntityManager em;

    public Long save(Customer customer) {
    em.persist(customer);
    return customer.getId();
    }

    public Customer readCustomer(Long id) {
    // Criteria query built here
    }

    }

    在上面的示例中,默认事务配置是必需的,这意味着在调用者组件中没有事务时,EJB 将创建一个新事务。如果调用者已经创建了一个事务 (CustomerService),则被调用的组件 (CustomerDao) 将继承该事务。这可以使用 @TransactionAttribute 进行定制。注解。

    如果您不使用 EJB 容器,我认为您上面的示例可能是等效的。

    已编辑 :为了简单起见,我在上面使用了无接口(interface) EJB,但是为那些使用接口(interface)来制作它们是一个好习惯,例如更可测试。

    关于hibernate - EntityManager 应该如何在一个很好的解耦的服务层和数据访问层中使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7856367/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com