JAVA08_org.springframework.transaction.UnexpectedRollbackException
Posted 所得皆惊喜
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA08_org.springframework.transaction.UnexpectedRollbackException相关的知识,希望对你有一定的参考价值。
- ①. 异常展示:Spring事务报错org.springframework.transaction.UnexpectedRollbackException
背景:在支付方法A上有@Transactional注解,在A方法里面调用了分红包方法B(也添加了@Transactional注解),我们在A方法里面对B方法进行try - catch处理,这个时候B方法抛出异常,导致Spring事务报错
serviceA有事务 @Transactional
serviceB有事务 @Transactional
serviceA.methodA()
doSomethingA();
try
serviceB.methodB; //这里面有异常标记为回滚, doSetRollbackOnly(status);
catch
//捕获异常转到commit时,由于已经标记为要回滚, 回滚并抛出新异常
doSomethingB();
- ②. 在分析问题之前对SPRING事务传播机制汇总如下:
- PROPAGATION_REQUIRED:如果当前没有事务,就新建一个事务,如果已经存在一个事务,就加入到这个事务中(默认策略)
- PROPAGATION_SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。
- PROPAGATION_MANDATORY:使用当前的事务,如果当前没有事务,就抛出异常。
- PROPAGATION_REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。
- PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
- PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
- PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_ REQUIRED类似的操作。
nested的子异常抛出,如果被catch外部插入成功
nested的子异常抛出,如果不被catch外部插入失败
nested外面异常抛出nest内部插入成功nest也会跟着回滚
- ③. UnexpectedRollbackException异常原因分析:
- 因为methodB的传播属性设置为PROPAGATION_REQUIRED,PROPAGATION_REQUIRED的意思是,当前有事务,则使用当前事务,当前无事务则创建事务。由于methodA的传播属性也为PROPAGATION_REQUIRED,所以methodA会创建一个事务,然后methodB与methodA使用同一个事务,methodB出现异常后,将当前事务标志位回滚,由于在methodA中做了trycatch处理,程序没有终止而是继续往下走,当事务commit时,check状态,发现,需要事务回滚,所以才会出现不可预知的事务异常:因为事务被标志位回滚,所以事务回滚
- methodA与methodB共用一个事务,methodB将事务标志为回滚,methodA中commit这个事务,然后出现事务已经被标志回滚(methodB标志的)的异常信息
- ④. 解决方案
- methodA与methodB在逻辑上不应该属于同一个事务,那么将methodB的事务传播属性修改为PROPAGATION_REQUIRES_NEW,这样,执行methodB时,会创建一个新的事务,不影响methodA中的事务
- 业务A与业务B在业务逻辑上就应该属于同一个事务,那么将methodA中的try catch去掉
- 业务A与业务B在业务逻辑上就应该属于同一个事务,但是methodB的失败与否不能影响methodA的事务提交,那么仍然在methodA中try catch methodB,并将methodB设置为PROPAGATION_NESTED,它的意思是,methodB是一个子事务,有一个savepoint,失败时会回滚到savepoint,不影响methodA,如果成功则A、B一起提交,A与B都是一个事务,只是B是一个子事务
- 业务A有无事务无影响,去掉业务A的@Transactional
以上是关于JAVA08_org.springframework.transaction.UnexpectedRollbackException的主要内容,如果未能解决你的问题,请参考以下文章