在另一个事务处于活动状态时手动启动新事务

Manually starting new transaction while another transaction is active

我想在已处于活动交易状态时执行以下步骤

  1. insert/update 一些记录
  2. select 所有这些记录都以非实体副本的形式保存在内存中
  3. 回滚第一步而不回滚父事务
  4. return 步骤 2 的结果。

我有这个

@Stateless
public class DBWorker {

    public Result doWork(boolean isPreview) {
        Result result;

        if(isPreview) {
            em.getTransaction().begin();
        }
        doSomeWork();
        List<SomeEntity> resultOfDoSomeWork = em.createQuery(..).getResultList();
        result = copyToNonEntity(resultOfDoSomeWork);

        if(isPreview)
            em.getTransaction().rollback();

        return result;
    }
}

但给出例外A JTA EntityManager cannot use getTransaction() IllegalStateException:A JTA EntityManager cannot use getTransaction()

您必须使用 @TransactionAttribute 注释来注释您的 EJB 方法。

特别是,你必须做这样的事情:

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void myMethod() {
   // do something
}

REQUIRES_NEW表示需要为业务方法启动一个新的事务。

注意将方法调用到另一个 EJB,因为如果从同一个 EJB 调用它,将不会创建新事务。

回滚

您可以回滚容器管理的事务:

  1. 抛出RuntimeException:容器会自动回滚事务。
  2. 抛出由 @ApplicationException(rollback=true) 注释的自定义异常:
  3. 通过调用EJBContext接口的setRollbackOnly方法:强制容器回滚事务,如果没有异常也是如此。

例如:

抛出 RuntimeException:

try {    
   // do something
} catch(SQLException e) {
   throw new EJBException();    
}

抛出自定义异常:

try {
   // do something
} catch(SQLException e) {
   throw new MyCustomException();
}

其中 MyCustomException class 类似于:

@ApplicationException(rollback=true)
public class MyCustomException extends Exception {
   // your custom methods
}

通过调用setRollbackOnly方法:

Context.setRollbackOnly();