我正在将 JPA 与 Spring 结合使用。如果我让 Spring 处理事务,那么假设 EntityManager 已正确注入(inject)到 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();
}
}
}
最佳答案
However, if I were to do transactions manually, I have to make sure to pass that instance of EntityManager into each of the DAOs within a transaction.
这就是你错的地方。来自 Spring Reference,JPA section :
The main problem with such a DAO is that it always creates a new EntityManager through the factory. You can avoid this by requesting a transactional EntityManager (also called "shared EntityManager" because it is a shared, thread-safe proxy for the actual transactional EntityManager) to be injected instead of the factory:
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();
}
}
The
@PersistenceContext
annotation has an optional attribute type, which defaults to PersistenceContextType.TRANSACTION. This default is what you need to receive a shared EntityManager proxy.
关于java - JPA 和 Spring 的手动事务服务和 DAO 层,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5812262/