Spring 事务传播机制Propagation核心概念事务传播行为当一个带有事务的方法 A 调用另一个带有事务的方法 B 时方法 B 如何使用当前已存在的事务。 由Transactional(propagation Propagation.XXX)指定一共 7 种。前提区分调用方外层方法被调用方内层方法7 种传播行为完整说明1. REQUIRED默认Propagation.REQUIRED如果当前存在事务加入该事务没有则新建事务。外层有事务 → 内外层共用同一个事务任何一方异常整体回滚外层无事务 → 内层新建独立事务最常用绝大多数业务场景默认使用。2. SUPPORTS Propagation.SUPPORTS有事务就加入没有事务就以非事务方式运行。外层存在事务加入外层事务外层无事务内层无事务执行不开启事务⚠️ 风险外层没事务时内层 SQL 自动提交出错不会回滚。3. MANDATORY Propagation.MANDATORY强制要求必须存在当前事务没有事务直接抛出异常。外层有事务加入事务外层无事务抛出IllegalTransactionStateException适合内层方法不能独立运行必须依托外层事务的场景。4. REQUIRES_NEW Propagation.REQUIRES_NEW新建独立事务暂停外层已有事务。重点内外层是两个完全独立事务外层有事务挂起外层事务开启内层新事务内层事务提交 / 回滚不影响外层事务外层回滚也不会回滚内层已提交事务典型场景记录操作日志哪怕主事务失败日志也要保存入库。5. NOT_SUPPORTED Propagation.NOT_SUPPORTED不支持事务如果存在事务先挂起事务以非事务执行。外层有事务 → 挂起内层无事务运行外层无事务 → 继续无事务运行内层操作不受事务控制操作即时生效。6. NEVER Propagation.NEVER禁止存在事务如果检测到外层有事务直接抛异常。外层无事务正常非事务执行外层存在事务抛出异常7. NESTED Propagation.NESTED嵌套事务基于保存点Savepoint运行。⚠️ 依赖底层数据库支持MySQL InnoDB 支持外层存在事务创建保存点内层是嵌套子事务内层异常只回滚到保存点外层事务可以选择提交或整体回滚外层异常连带内层一起回滚外层无事务新建事务和REQUIRES_NEW关键区别REQUIRES_NEW两个独立事务互不干涉NESTED属于同一个外层事务下的子事务外层回滚会连带子事务高频面试对比表格传播属性外层有事务外层无事务REQUIRED加入当前事务创建新事务SUPPORTS加入当前事务无事务运行MANDATORY加入当前事务抛异常REQUIRES_NEW挂起外层新建独立事务创建新事务NOT_SUPPORTED挂起外层无事务运行无事务运行NEVER抛异常无事务运行NESTED创建保存点嵌套子事务创建新事务经典坑面试高频同一个类内方法自调用事务传播失效Service public class OrderService { Transactional public void a() { // 直接调用本类b()不走AOP代理传播机制不生效 b(); } Transactional(propagation Propagation.REQUIRES_NEW) public void b(){} }原因内部调用绕过 Spring AOP 代理。解决方案通过上下文获取代理对象调用。try-catch捕获内层异常能否阻止回滚 在REQUIRED共用事务下 内层抛出异常 → 事务标记回滚点即使外层 catch最终依然回滚。 想要外层捕获异常不回滚需要REQUIRES_NEW或者NESTED。使用场景建议常规业务新增 / 修改REQUIRED默认操作日志独立落库主流程失败日志保留REQUIRES_NEW子操作允许单独回滚、主事务可继续执行NESTED方法必须在事务内部执行MANDATORY
Spring 事务传播机制(Propagation)
Spring 事务传播机制Propagation核心概念事务传播行为当一个带有事务的方法 A 调用另一个带有事务的方法 B 时方法 B 如何使用当前已存在的事务。 由Transactional(propagation Propagation.XXX)指定一共 7 种。前提区分调用方外层方法被调用方内层方法7 种传播行为完整说明1. REQUIRED默认Propagation.REQUIRED如果当前存在事务加入该事务没有则新建事务。外层有事务 → 内外层共用同一个事务任何一方异常整体回滚外层无事务 → 内层新建独立事务最常用绝大多数业务场景默认使用。2. SUPPORTS Propagation.SUPPORTS有事务就加入没有事务就以非事务方式运行。外层存在事务加入外层事务外层无事务内层无事务执行不开启事务⚠️ 风险外层没事务时内层 SQL 自动提交出错不会回滚。3. MANDATORY Propagation.MANDATORY强制要求必须存在当前事务没有事务直接抛出异常。外层有事务加入事务外层无事务抛出IllegalTransactionStateException适合内层方法不能独立运行必须依托外层事务的场景。4. REQUIRES_NEW Propagation.REQUIRES_NEW新建独立事务暂停外层已有事务。重点内外层是两个完全独立事务外层有事务挂起外层事务开启内层新事务内层事务提交 / 回滚不影响外层事务外层回滚也不会回滚内层已提交事务典型场景记录操作日志哪怕主事务失败日志也要保存入库。5. NOT_SUPPORTED Propagation.NOT_SUPPORTED不支持事务如果存在事务先挂起事务以非事务执行。外层有事务 → 挂起内层无事务运行外层无事务 → 继续无事务运行内层操作不受事务控制操作即时生效。6. NEVER Propagation.NEVER禁止存在事务如果检测到外层有事务直接抛异常。外层无事务正常非事务执行外层存在事务抛出异常7. NESTED Propagation.NESTED嵌套事务基于保存点Savepoint运行。⚠️ 依赖底层数据库支持MySQL InnoDB 支持外层存在事务创建保存点内层是嵌套子事务内层异常只回滚到保存点外层事务可以选择提交或整体回滚外层异常连带内层一起回滚外层无事务新建事务和REQUIRES_NEW关键区别REQUIRES_NEW两个独立事务互不干涉NESTED属于同一个外层事务下的子事务外层回滚会连带子事务高频面试对比表格传播属性外层有事务外层无事务REQUIRED加入当前事务创建新事务SUPPORTS加入当前事务无事务运行MANDATORY加入当前事务抛异常REQUIRES_NEW挂起外层新建独立事务创建新事务NOT_SUPPORTED挂起外层无事务运行无事务运行NEVER抛异常无事务运行NESTED创建保存点嵌套子事务创建新事务经典坑面试高频同一个类内方法自调用事务传播失效Service public class OrderService { Transactional public void a() { // 直接调用本类b()不走AOP代理传播机制不生效 b(); } Transactional(propagation Propagation.REQUIRES_NEW) public void b(){} }原因内部调用绕过 Spring AOP 代理。解决方案通过上下文获取代理对象调用。try-catch捕获内层异常能否阻止回滚 在REQUIRED共用事务下 内层抛出异常 → 事务标记回滚点即使外层 catch最终依然回滚。 想要外层捕获异常不回滚需要REQUIRES_NEW或者NESTED。使用场景建议常规业务新增 / 修改REQUIRED默认操作日志独立落库主流程失败日志保留REQUIRES_NEW子操作允许单独回滚、主事务可继续执行NESTED方法必须在事务内部执行MANDATORY