Transaction rolled back because it has been marked as rollback-only 的中文翻译是:事务已回滚,因为它已标记为仅回滚。??????越看越懵...
🔴其实很简单,一般就一种情况:你某一个代码块使用了try catch
下面我来举列子说明一下出现的情况吧
A实现类的方法
@Transactional(rollbackFor = Exception.class)
public void A(Boolean bool) {
try {
workItemTemplateHistoryService.B(bool);
} catch (Exception e) {
e.printStackTrace();
}
}
B实现类的方法
@Transactional(rollbackFor = Exception.class)
public void B(Boolean bool) throws BizException {
if (bool) {
throw new BizException("我是故意抛出的异常");
}
}
前提条件是保证A方法和B方法事务时生效的:不同一个实现类且都加上事务注解。
A方法调用了B方法,并且进行try拦截异常。
执行结果:
企业微信截图_1678957277700.png
企业微信截图_16789572602250.png
我们会发现有两处异常日志,为什么会这样呢?这是我们这次需要了解的。
当A方法的事务(REQUIRED),B方法的事务(REQUIRED),A调用B方法,在spring中,spring将会把这些事务合二为一。
当整个方法中每个子方法没报错时,整个方法执行完才提交事务。
如果某个子方法有异常,spring将该事务标志为rollback only。如果这个子方法没有将异常往上抛,或者主父方法将子方法抛出的异常捕获了,那么,该异常就不会触发事务进行回滚,事务就会在整个方法执行完后就会提交,这时就会造成Transaction rolled back because it has been marked as rollback-only的异常。(由于异常被标记了rollback only,但是又执行了commit,此时就会报这个错)
这里我提供两种解决办法:
1.去掉方法A try 方法B的异常拦截
2.关闭方法B的事务(如果方法B被其它方法调用,则重载一个没有事务的方法B)