事务嵌套下的异常解决办法

711 阅读2分钟

一、事务嵌套下出现的异常及异常出现的原因

1、事务嵌套,业务逻辑上存在事务嵌套的情况。例如:方法methodA()中有methodB(),两个方法都有操作数据库的业务代码insert()。

image.png

执行methodA后,在一定场景下会抛出异常,异常如下:Transaction rolled back because it has been marked as rollback-only

2、原因:当spring开启事务时,如果不修改propagation的参数,则事务传播默认方式是propagation.REQUIRED。即如果没有事务则新开启一个事务,如果已经存在事务则加入这个事务。当内层事务异常的情况下,如果是这种传播方式,正常来讲是需要回滚的,但是spring给内层事务做了一个rollback的标记。所以当内层事务抛出的异常被外层try-catch时,外层事务正常执行,但在最后提交的时候发现,内层被标记了rollbck,就会抛出Transaction rolled back because it has been marked as rollback-only这个异常

二、事务嵌套异常解决方法

1、第一种情况

内层事务异常的情况下只回滚内层事务,但不影响外层事务提交。修改内层事务的事务传播方式,@Transactional注解内加上propagation = Propagation.REQUIRES_NEW。

image.png 2、第二种情况

methodB方法不是通用的方法,内层异常的情况下,回滚全部事务,让内层事务抛出的异常被外层事务的try–catch处理,设置手动回滚TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); 或者外层不要try–catch处理,异常直接抛到最外层。

image.png 3、第三种情况

methodB方法是通用的方法,只是在这个地方使用,可以直接把内层的事务去了,让它和外层合并成一个事务 image.png

4、特殊情况

methodA和methodB在同一个类中,那就不会出现Transaction rolled back because it has been marked as rollback-only异常 原因:因为注解的生效是通过代理模式实现的,同一个类下相互调用,被调用者是没法生成代理方法的,即method2的事务根本就没有生效。所以也不会出现异常。

image.png