使用Spring的JPA手动事务服务和DAO层

5

我正在使用Spring的JPA。如果我让Spring处理事务,那么假设EntityManager已经正确注入到DAO中,我的Service层将如下所示:

MyService {

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

然而,如果我要手动进行交易,我必须确保将这个EntityManager实例传递到事务中的每个DAO中。有什么好的重构方法吗?我觉得使用new MyDaoA(em)或像doSomething(em)这样在每个DAO方法中传递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();
       }
    }
}
3个回答

3
然而,如果我要手动进行交易,我必须确保将那个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 代理所需的。


1
我仍不清楚如何在服务层和 DAO 层中进行手动事务处理。 - Langali
a) 如果我必须这样做,我可能会使用TransactionTemplate或JpaTemplate。 b) 不要这么做,太麻烦了。 - Sean Patrick Floyd
抱歉,这超出了本问题的范围。请阅读Spring参考文档,特别是事务管理和ORM部分(http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/transaction.html 和 http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/orm.html)。提示:异常转换是您的好朋友。 - Sean Patrick Floyd

1
将此添加到您的Spring配置中。
<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 );

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接