【问题标题】:Manual Transactional Service and DAO layer for JPA with Spring使用 Spring 的 JPA 的手动事务服务和 DAO 层
【发布时间】:2011-08-14 07:29:04
【问题描述】:

我在 Spring 中使用 JPA。如果我让 Spring 处理事务,那么假设 EntityManager 已正确注入 DAO,这就是我的服务层的样子:

MyService {

   @Transactional
   public void myMethod() {
       myDaoA.doSomething();
       myDaoB.doSomething();
    }
}

但是,如果我要手动执行事务,我必须确保将该 EntityManager 实例传递到事务中的每个 DAO。知道如何更好地重构吗?我觉得做 new MyDaoA(em) 或将 em 传递给每个 DAO 方法(如 doSomething(em))很难看。

MyService {

   private EntityManagerFactory emf;

   public void myMethod() {
       EntityManager em = emf.createEntityManager();
       EntityTransaction tx = em.getTransaction();
       MyDaoA myDaoA = new MyDaoA(em);
       MyDaoB myDaoB = new MyDaoB(em);
       try {
           tx.begin();
           myDaoA.doSomething();
           myDaoB.doSomething();
           tx.commit();
       } catch(Exception e) {
           tx.rollback();
       }
    }
}

【问题讨论】:

    标签: java hibernate spring jpa transactions


    【解决方案1】:

    我猜有点在黑暗中拍摄,但你知道你能做到吗:

    TransactionInterceptor.currentTransactionStatus().setRollbackOnly();

    这通常会消除您希望/需要在具有声明性事务的系统中使用程序化事务的大多数情况。

    【讨论】:

      【解决方案2】:

      但是,如果我要进行交易 手动,我必须确保通过 EntityManager 的那个实例到 交易中的每个 DAO。

      这是你错的地方。来自 Spring 参考,JPA section

      这种 DAO 的主要问题是 它总是创造一个新的 EntityManager 通过工厂。 你 可以通过请求避免这种情况 事务性EntityManager(也 称为“共享 EntityManager”,因为 它是一个共享的、线程安全的代理 实际交易 EntityManager) 被注入 工厂:

      public class ProductDaoImpl implements ProductDao {
      
          @PersistenceContext
          private EntityManager em;
      
          public Collection loadProductsByCategory(String category) {
             Query query = em.createQuery(
                              "from Product as p where p.category = :category");
             query.setParameter("category", category);
             return query.getResultList(); 
          }
      }
      

      @PersistenceContext 注释有 一个可选的属性类型,它 默认为 PersistenceContextType.TRANSACTION。 这个默认值是你需要的 接收共享的 EntityManager 代理

      【讨论】:

      【解决方案3】:

      将此添加到您的弹簧配置中

      <bean p:entityManagerFactory-ref="emf" class='org.springframework.orm.jpa.support.SharedEntityManagerBean' />
      

      现在你可以在你的 dao 中 @Autowired EntityManager

      对于事务管理,由于您已经使用 spring 和 @Transactional 注释,我假设您已经在 spring.xml 中声明了一个事务管理器

      所以使用spring的事务管理

      作为

      transactionStatus = platformTransactionManager.getTransaction(new DefaultTransactionDefinition());
      // do your work here 
      platformTransactionManager.commit(transactionStatus );
      

      【讨论】:

        猜你喜欢
        • 2013-05-16
        • 2011-04-22
        • 2017-06-07
        • 2019-11-11
        • 2012-01-25
        • 1970-01-01
        • 2013-07-01
        • 2012-11-26
        • 1970-01-01
        相关资源
        最近更新 更多