spring事务机制
spring 事务
1. 事务传播机制
REQUIRED : 如果当前没有事务,新建事务执行,存在事务,加入事务中运行
SUPPORTS : 支持当前事务。 如果当前存在事务,则加入事务,否则以非事务方式运行
MANDATORY : 强制要求事务,使用当前事务,如果没有抛出异常
NO_SUPPORTED: 不支持当前事务,如果存在事务,把事务挂起以非事务方式运行。
REQUIRED_NEW:需要事务,创建一个新的事务
NEVER: 不需要事务,当前存在事务,抛异常
NESTED : 如果当前存在事务,则在嵌套事务运行,否则新建事务

REQUIRED 和 NESTED 区别:
两个方法都加了事务注解,并且两个方法都会受到到事务管理的拦截器增强,并且事务传播的方式都是默认的,也就是REQUIRED,当已经存在事务的时候就加入事务,没有就创建事务。这里A和B都受事务控制,并且是处于同一个事务的。
A调用B,A中抓了B的异常,当B发生异常的时候,B的操作应该回滚,但是A吃了异常,A方法中没有产生异常,所以A的操作又应该提交,二者是相互矛盾的。
spring的事务关联拦截器在抓到B的异常后就会标记rollback-only为true,当A执行完准备提交后,发现rollback-only为true,也会回滚,并抛出异常告诉调用者。
1 | @Transactional(propagation=Propagation.REQUIRED) |
上述代码 则只有b的插入回滚,a不回滚。原因是在进入NESTED方法时事务保存了当前b的savepoint,b异常只会回滚到b的savepoint
同时若在a方法中抛出异常,则a,b插入都会回滚
1 | @Transactional(propagation=Propagation.REQUIRED) |
NESTED嵌套事务的奥秘之处—–它能让事务部分回滚(通过savepoint)
NESTED的回滚特性
- 主事务和嵌套事务属于同一个事务
- 嵌套事务出错回滚不会影响到主事务
- 主事务回滚会将嵌套事务一起回滚了
NESTED事务跟REQUIRED事务区别就在这里,NESTED事务是回滚到回滚点,而回滚点生成是在进入内嵌事务的时候,外面事务是不会回滚的
2. 声明式事务不生效原因
数据库不支持事务
抛出检查下异常
方法内调用事务方法
创建类不接受spring管理
@Transaction修饰方法不是public
捕获了异常,未抛出
- 配置多了事务管理器 如Mongo和mysql
方法内互相调用失效问题: 绕过代理对象,事务使用代理对象来控制的,解决使用aspectj
引入
aop-start; spring-boot-start-aop开启
@EnableAspectJautoProxyAopContext.currentProxy()