执行"多个" JPA交易成单一的交易"

时间:2014-11-25 14:25:46

标签: java jpa transactions

我有两个单独的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();
}

我不确定我建议的设计。

你有什么建议?

2 个答案:

答案 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();
}

这会将事务管理提升到正在执行的查询之上并很好地分离关注(据我所知);