Spring事务及事务传播
Spring 并不直接支持事务,只有当数据库支持事务时,Spring 才支持事务。Spring中有声明式和编程式(淘汰)事务,声明式事务是基于Spring AOP方式实现的。所谓事务传播机制,也就是在事务在多个方法的调用中是如何传递的,是重新创建事务还是使用父方法的事务?父方法的回滚对子方法的事务是否有影响?这些都是可以通过事务传播机制来决定的。
**声明式事务隔离级别:**较SQL标准的四种隔离级别多一个,为使用数据库默认的隔离级别(isolation_default)。
声明式事务传播特性:传播特性是Spring在当前线程内,处理多个数据库操作方法事务时所做的一种事务应用策略,且作用于内层的方法上(多个方法的嵌套调用,最外层方法不存在传播).
Spring提供的事务七大传播方式:
- PROPAGATION_REQUIRED (必须的,默认)– 支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
- PROPAGATION_SUPPORTS(支持) – 支持当前事务,如果当前没有事务,就以非事务方式执行。
- PROPAGATION_MANDATORY (强制)– 支持当前事务,如果当前没有事务,就抛出异常。
- PROPAGATION_REQUIRES_NEW (必须要新的) – 新建事务,如果当前存在事务,把当前事务挂起。
- PROPAGATION_NOT_SUPPORTED (不支持)– 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
- PROPAGATION_NEVER(从不) – 以非事务方式执行,如果当前存在事务,则抛出异常。
- PROPAGATION_NESTED(嵌套) – 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。
当前是指外层事务。
propagation_required(必须的,默认): 如果外层事务不存在,内层就主动开启事务;否则使用外层事务
propagation_supports(支持) : 如果外层事务不存在,就不使用事务;否则使用外层事务支持当前事务,如果当前没有事务,就以非事务方式执行。
propagation_mandatory(强制) : 如果外层事务不存在,就抛出异常;否则使用外层事务
propagation_requires_new(必须要新的) : 总是开启一个新事务;如果存在外层事务,就将外层事务挂起
propagation_not_supported(不支持) : 总是不开启事务;如果存在外层事务,就将外层事务挂起
propagation_never(从不) :总是不使用事务;如果存在外层事务,就抛出异常.与mandatory相反
propagation_nested(嵌套) :如果外层事务不存在,就主动创建事务;否则创建嵌套的子事务.外层事务若回滚,会带着子事务一同回滚;子事务若回滚,则到 savepoint (即 刚进入 子事务的暂存点),不会影响到外层事务
基本知识
- 事务传播机制只适用于不同bean之间方法的调用,如果一个bean中的两个方法互相调用并不会使用到事务传播。
- 事务方法里如果抛RuntimeException,则会导致所有相关事务回滚,个别事务传播机制有点特殊,我们下面会讲到。
- 事务方法里如果抛Throwable或者Exception,默认不会导致相关事务回滚,一般都会在出异常的地方提交,就有可能出现部分提交的问题。但可以配置rollback-for属性来控制。
不同传播特性间的对比:
https://blog.csdn.net/konaji/article/details/79626818
nested 与 required 外层事务不存在,都会主动创建事务,那他们两者有什么区别?
required 外内层方法使用的是同一个事务,只要发生异常,外内层都要回滚;nested 内层使用的是外层的子事务,发生异常回滚时,要视情况而定(如上7中解释).
nested 与 requires_new 在内层事务异常回滚时,都不会影响到外层事务,那他们两者有什么区别?
nested使用的是外层事务的子事务,回滚时,会回到对应的 savepoint ,且外层事务的回滚会带动嵌套内层事务回滚;requires_new的外内层使用的是两个独立的事务,内层事务的操作,不会影响外层事务.