spring 事务传播问题
工作中碰到的一个小问题:
背景:
方法1、2 均在spring aop事务管理下
现执行结果: 方法2抛异常,方法2回滚,方法1也回滚了
期望结果:方法2抛异常,方法2回滚,方法1不回滚
思考
spring事务什么时候会自动回滚?
Spring事务回滚机制是这样的:当所拦截的方法(@Transactional或者通过xml配置)有指定异常抛出,事务才会自动进行回滚!
异常抛出?
即方法中出现的指定异常,只有在被事务管理器捕捉到以后,事务才会据此进行事务回滚
哪些异常会回滚?
默认Error与RuntimeException,不包括checkedException 如IOException
查看源码可知默认情况为这两种异常:
有rollBackFor的情况,则根据设置的异常来定
由上述知识铺垫分析下问题,发现方法2抛出异常被catch住之后,正常情况下,不应该会导致方法1被回滚
再思考:
配置:
发现事务传播属性配置的
7种Propagation :
- PROPAGATION_REQUIRED:默认事务类型,如果没有,就新建一个事务;如果有,就加入当前事务。适合绝大多数情况。
- PROPAGATION_REQUIRES_NEW:如果没有,就新建一个事务;如果有,就将当前事务挂起。
- PROPAGATION_NESTED:如果没有,就新建一个事务;如果有,就在当前事务中嵌套其他事务。
- PROPAGATION_SUPPORTS:如果没有,就以非事务方式执行;如果有,就使用当前事务。
- PROPAGATION_NOT_SUPPORTED:如果没有,就以非事务方式执行;如果有,就将当前事务挂起。即无论如何不支持事务。
- PROPAGATION_NEVER:如果没有,就以非事务方式执行;如果有,就抛出异常。
- PROPAGATION_MANDATORY:如果没有,就抛出异常;如果有,就使用当前事务。
由于add*方法是默认的required,所以方法2的事务应该是:
方法2的父方法有事务,故加入其事务。
当其抛出异常时,符合spring事务回滚的条件,故回滚该事务
结论:
如果想要达到目的,只需要将方法2的事务传播属性改为PROPAGATION_NESTED即可