Spring事务
默认配置下Spring只会回滚运行时、未检查异常(继承自RuntimeException)或Error
@Transactional注解只能应用到public方法
事务隔离级别
- DEFAULT
- READ_UNCOMMITED
- READ_COMMITED
- REPEATABLE_READ
- SERIALIZABLE
事务传播机制
- required,如果当前线程已经在一个事务中,则加入该事务,否则,新建一个事务
- support,如果当前线程已经在一个事务中,则加入,否则,不管
- mandatory,当前线程必须在事务中,否则抛出异常
- require_new,无论如何都会创建一个新事务,如果当前已有,挂起当前事务
- not_supported,在事务中,就挂起事务
- never,在事务中就抛出异常
- nested,嵌套事务,
举例
两个事物,事物A和事物B,其中在事物A中调用了事物B,那么会出现两种异常情形:
- A成功,B回滚
- A回滚,B成功
required
情况1,2,B会加入A的事务,B回滚导致AB都会回滚
required_new
俩事务各不影响
nested
嵌套的,B是依赖A的,A成功则成功,否则无论B成功或失败,都回滚
原理分析
开启事务时,针对不同的传播级别,事务行为有什么区别
在尝试获取事务信息时,如果当前已经存在一个事务,会根据传播级别做一些不同的处理
- 如果不存在事务,则创建一个新的TransactionStatus对象
- 如果存在事务,则进行ExistingTransaction判断
- 如果是Never,直接抛异常
- 如果是not_supported,挂起事务,将当前事务设置为null,还原ThreadLocal对象为无事务状态
- 如果是required_new,则挂起当前事务,创建一个新事务,执行doBegin
- 如果是nested,则创建一个savePoint
- 如果是require,则把newTransaction标志置false
事务回滚时,传播级别对事务行为的影响
- 如果newTransaction为true,则执行回滚
- 如果有savePoint,则回滚到savePoint
- 否则不会真正回滚,只会设置回滚标志位
事务提交时,传播级别对事务行为的影响
- 即使事务方法没有异常,commit时依然有可能回滚
- 对于required,只要父或子设置了回滚标志,就会全部回滚,因为子事务都会加入到父事务中
- 只有newTransaction标志位为true,才会执行commit