@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
启动时TransactionAttribute
REQUIRED
因此TransactionSynchronizationRegistry
将事务状态打印为启动时0
。
在抛出运行时异常的方法调用后,事务状态将自动1
。但是,当将事务属性称为REQUIRES_NEW
的method_B
时,仍然TransactionSynchronizationRegistry
打印1
。
根据我的理解,它应该开始一个新的事务,并且传输状态应该显示为method_B
中的0
?
从同一 Bean 的方法直接调用 Bean 方法不会通过事务拦截器,因此不会执行事务属性检查。
有两种方法可以解决此问题:
@Resource
private ManagedExecutorService mes;
....
mes.execute(()->method_B());
....
这将通过拦截器/代理,并且在不同的线程中将自动启动新事务。 这里的缺点是,如果新事务失败,则method_A
中的事务将不会回滚,因为它们位于不同的线程中