我正在使用JPA和Spring.如果我让Spring处理事务,那么假设EntityManager已正确注入DAO,这就是我的服务层的样子:
MyService {
@Transactional
public void myMethod() {
myDaoA.doSomething();
myDaoB.doSomething();
}
}
但是,如果我要手动执行事务,我必须确保将EntityManager的实例传递到事务中的每个DAO中.任何想法如何更好地重构?我很难做新的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.