我有两个单独的JPA事务T1()和T2():
public void T1() {
em = getEntityManager();
em.getTransaction().begin();
...
//some statements
...
em.getTransaction().commit();
}
和
public void T2() {
em = getEntityManager();
em.getTransaction().begin();
...
//some statements
...
em.getTransaction().commit();
}
现在,我有一个需要执行T1()和T2()的组合事务。
以下代码示例应该是错误的:
public void T12() {
em = getEntityManager();
em.getTransaction().begin();
T1();
T(2)
em.getTransaction().commit();
}
以下代码无法确保T1()和T2()的失败或成功,因为如果T1()成功,T2()可能会失败而无法回滚T1():
public void T12() {
T1();
T(2);
}
我应该按如下方式更改T1()(和T2())的设计:
public void T1(EntityTransaction trans) {
if (trans != null) {
trans.begin();
}
...
//some statements
...
if (trans != null) {
trans.commit();
}
}
当作为独立事务执行时,我使用:
void singleTransction() {
...
trans = em.getTransaction();
trans.begin();
T1(trans);
trans.commit();
}
在已经启动的交易中执行时,我使用:
void manyTransactions() {
....
trans = em.getTransaction();
trans.begin();
T1(null);
T2(null);
T3(null);
trans.commit();
}
我不确定我建议的设计。
你有什么建议?
答案 0 :(得分:1)
您可以使用JTA和em.joinTransaction()
。
或者您可以检查是否需要在方法中开始/提交。我们的想法是让您的方法足够聪明,以便在没有管理交易的情况下管理交易,如果调用者正在管理交易,则不管理交易。
public void T1() {
em = getEntityManager();
boolean managingTransaction = !em.getTransaction.isActive();
if (managingTransaction) {
em.getTransaction().begin();
}
...
//some statements
...
if (managingTransaction) {
em.getTransaction().commit();
}
}
这是有效的,假设getEntityManager()
每次在同一个线程中调用它时都会给你相同的实体管理器(这是典型的模式)。
我还要注意,你需要额外的错误处理代码来rollback()
事务处理(我假设你知道这一点,但有人来看这个问题可能没有意识到你的代码不是一个完整的例子)。
答案 1 :(得分:0)
我可能会更改设计并将实体管理器作为要执行的查询的参数。
public void T1(EntityManager manager) {
// do work with entity manager
}
public void T2(EntityManager manager) {
// do work with entity manager
}
//This is pseudo - example code. It won't compile
public static void main(String[] args) {
EntityManager em = getEntityManager();
EntityTransaction tx = em.getTransactions().begin();
T1(manager);
T2(manager);
tx.commit();
}
这会将事务管理提升到正在执行的查询之上并很好地分离关注(据我所知);