先来看个异常
org.springframework,transaction,UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only
下面看看抛出此异常的伪代码
@Slf4j
@Service
public class A {
@Resource
private B b;
@Transactional(rollbackFor = Exception.class)
public void aMethod(){
try{
b.exec();
} catch (Exception e){
log.info("异常打印");
}
//业务要求,b.bMethod() 抛出异常后 原业务需要继续执行
}
}
@Service
public class B {
@Transactional(rollbackFor = Exception.class)
public void exec(){
// 业务执行 可能抛出异常
}
}
原因:
????????A调用B,如果B抛出Exception,A中捕获Exception但是并不继续向外抛出,最后会出现此异常。
????????纠其原理其实很简单,在B返回的时候,transaction被设置为rollback-only了,但是A正常消化掉,没有继续向外抛。 那么A结束的时候,transaction会执commit操作,但是transaction已经被设置为 rolback-only了。?
上面解释了抛出此异常的原因,下面来分析在此业务场景下如何解决这个问题:
????????因业务要求,B.exec抛出异常后原业务需要继续执行,所以这里不能就不能直接将异常抛出,需要将B.exec上的事务注解去除,将嵌套异常给断开
? ? ? ? 注:若B.exec业务可以单独在自己的事务中执行,那么可以新开事务(注意:若新开事务,B.exec执行完毕事务回直接提交,需考虑业务的整体性)