TransactionAttribute.REQUIRES_NEW不使用容器管理的事务在 EJB Bean 中启动新事务


@Singelton
public Class className {

@Resource
private TransactionSynchronizationRegistry tsr;

@Resource 
private Transaction 

@TransactionAttribute(TransactionAttributeType.REQUIRED)
public method_A () {

System.out.println(tsr.getTransactionStatus()); // prints 0 

method_call_which_throw_persistence_exception(); 

System.out.println(tsr.getTransactionStatus());  // prints 1

method_B();

}

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public method_B () {
System.out.println(tsr.getTransactionStatus());  // prints 1
}                
} 

注意:

  • 交易状态0 = active
  • 交易状态1 = markedForRollback

正如我附加上面的代码一样,在使用容器管理事务的 Ejb singelton bean 中存在 2 种方法。method_A启动时TransactionAttributeREQUIRED因此TransactionSynchronizationRegistry将事务状态打印为启动时0

在抛出运行时异常的方法调用后,事务状态将自动1。但是,当将事务属性称为REQUIRES_NEWmethod_B时,仍然TransactionSynchronizationRegistry打印1

根据我的理解,它应该开始一个新的事务,并且传输状态应该显示为method_B中的0

从同一 Bean 的方法直接调用 Bean 方法不会通过事务拦截器,因此不会执行事务属性检查。

有两种方法可以解决此问题:

@Resource
private ManagedExecutorService mes;

....
mes.execute(()->method_B());
....

这将通过拦截器/代理,并且在不同的线程中将自动启动新事务。 这里的缺点是,如果新事务失败,则method_A中的事务将不会回滚,因为它们位于不同的线程中

最新更新