当前位置: 首页 > 面试题库 >

在良好分离的服务层和数据访问层中应如何使用EntityManager?

终睿
2023-03-14
问题内容

与我的其他问题有些相关,是否应该从数据访问层(或接口)返回原始的Hibernate注释POJO?,我在创建很好的解耦层方面很有经验,但是没有使用Hibernate或J2EE/JPA。我一直在看文档和教程,却对如何以一种优雅的方式使用EntityManger感到困惑,因为它似乎既负责事务(我想在服务层上做)又负责持久性方法(我想要做)保留在数据访问层中)。我应该在服务层创建它,然后将其注入数据访问层,还是有更好的方法?下面的伪Java大致显示了我正在考虑的工作。

编辑:下面的我的伪代码本质上是从hibernateJPA教程中获取的,并针对层分离进行了修改,并不反映该产品正在开发为在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和EntityManager出现以来一直存在的争论,许多人认为DAO本身就已经存在。答案取决于您正在开发的应用程序类型,但是在大多数情况下,您需要:

  • 使用JPA标准或自定义查询 。在这种情况下,您可能不想将业务逻辑与查询创建混在一起。这将导致方法繁多,并违反了单一责任原则。
  • 尽可能重用您的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容器,那么我认为您上面的示例可能是等效的。

编辑 :为简单起见,我在上面使用了无接口EJB,但是对这些接口使用接口以使其更具可测试性是一个很好的做法。



 类似资料:
  • 开发手册的这一部分关注于中间层开发,并明确描述了这一层的数据访问职责。 先是,详细阐述了Spring全面的事务管理支持,随后,详细说明了Spring Framework如何支持多种中间层数据访问的框架和技术。 第 10 章 事务管理 第 11 章 DAO支持 第 12 章 使用JDBC进行数据访问 第 13 章 使用ORM工具进行数据访问 目录 10. 事务管理 10.1. 简介 10.2. 动机

  • 当条目发生更改时,我们希望在SQL数据库中添加一个UpdateDatetime列。 在微服务架构中,(a)所有3个访问表的服务现在都需要在其API中包含Updatedate吗,(b)或者微服务会共享同一个数据访问层吗? 如果是字母(a),他们有什么方法可以使开发更容易吗? 我们正在询问与微服务相关的开发人员维护,因为我们可能有 10 个应用程序与 1 个表交互。如果添加的表或列中有错误,我们需要通

  • 在我的示例中,我有一个Hibernate实体和一个DAO。 当我以这种方式使用DAO时 数据库中只保存了一行(Action2)。当我删除注释时,两行(Action1和Action2)都被保存(这是我需要的行为)。我的问题是服务层上的事务注释如何影响事务(方法executeTransaction())的执行。为什么没有服务层上的事务性注释,这两行都保存在数据库中,而只有最后一行与此注释一起保存?

  • 3.4. 中间层(数据访问) 3.4.1. 在XML里更为简单的声明性事务配置 Spring 2.0关于事务的配置方式发生了重大的变化。早先的1.2.x版本的配置方式仍然有效(并且受支持),但是新的方式明显更加简洁,并成为最推荐的方式。 Spring 2.0 同时提供了AspectJ切面库,你可以使用它来生成更漂亮的事务性对象 - 甚至可以不是由Spring事务性容器产生的。 标题为 第 10 章

  • 4.1 ABP应用层 - 应用服务 应用服务用于将领域(业务)逻辑暴露给展现层。展现层通过传入DTO(数据传输对象)参数来调用应用服务,而应用服务通过领域对象来执行相应的业务逻辑并且将DTO返回给展现层。因此,展现层和领域层将被完全隔离开来。在一个理想的层级项目中,展现层应该从不直接访问领域对象。 4.1.1 IApplicationService接口 在ABP中,一个应用服务需要实现 IAppl

  • 问题内容: 我正在Django中编写一个项目,我发现文件中有80%的代码。这段代码令人困惑,并且在一段时间之后,我不再了解实际发生的事情。 这是困扰我的事情: 我发现模型级别(应该只负责处理数据库中的数据)在发送电子邮件,使用API​​到其他服务等方面也很丑陋。 另外,我发现在视图中放置业务逻辑也是不可接受的,因为这样很难控制。例如,在我的应用程序中,至少有三种方法来创建的新实例,但从技术上讲,它