我在Spring中使用JPA。如果我让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();
}
}
}
答案 0 :(得分:3)
但是,如果我要做交易 手动,我必须确保通过 那个EntityManager实例进入 交易中的每个DAO。
这是你错的地方。从Spring Reference,JPA section:
这样一个DAO的主要问题是 它总是创造一个新的 EntityManager通过工厂。 您 通过请求a可以避免这种情况 事务性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 :(得分:1)
将此添加到您的弹簧配置
<bean p:entityManagerFactory-ref="emf" class='org.springframework.orm.jpa.support.SharedEntityManagerBean' />
现在你可以在你的dao中使用@Autowired EntityManager
对于事务管理,因为你已经使用了spring和@Transactional注释,我假设你已经在spring.xml中声明了一个事务管理器
所以使用spring的事务管理
as
transactionStatus = platformTransactionManager.getTransaction(new DefaultTransactionDefinition());
// do your work here
platformTransactionManager.commit(transactionStatus );
答案 2 :(得分:0)
我想在黑暗中拍摄,但你知道你可以做到:
TransactionInterceptor.currentTransactionStatus().setRollbackOnly();
这通常会消除您希望/需要在系统中使用程序化事务的大多数情况,否则这些事务具有声明性事务。