java中事务的propagation属性本质是控制方法嵌套调用时事务的延续方式,决定加入、挂起、新建或拒绝当前事务上下文,仅在spring代理调用且均为public方法时生效,默认值为required。

Java 中事务的 propagation 属性 本质是控制“一个带事务的方法被另一个方法调用时,事务该怎么延续”,不是单纯设个开关,而是决定它该“加入”“挂起”“新建”还是“拒绝”当前事务上下文。配置得当,能避免事务嵌套异常、数据不一致或资源浪费。
明确 propagation 的作用场景
它只在方法间嵌套调用时生效——比如 service A 的方法调用了 service B 的方法,且两个方法都标注了 @Transactional。如果 B 方法没加注解,或者调用发生在同一类内(非代理调用),propagation 就不起作用。
- 必须通过 Spring 代理对象调用(即走 AOP 链路),直接 this.methodB() 不触发事务传播
- 只对 public 方法有效,private/protected 方法加注解无效
- 默认值是 Propagation.REQUIRED,多数业务无需显式指定
常用 propagation 值及典型用法
REQUIRED(最常用):有事务就加入,没事务就新建。适合绝大多数增删改操作。
例如 checkout() 调用 pay() 和 sendOrder(),三者都用 REQUIRED,整个流程在一个事务里,任一失败全部回滚。
REQUIRES_NEW(关键隔离):强制新建事务,原事务挂起。适合日志记录、异步通知等“必须成功”的子操作,不受外层事务成败影响。
比如下单成功后发短信,即使后续库存扣减失败导致订单回滚,短信仍已发出——因为发短信方法用了 REQUIRES_NEW。
NOT_SUPPORTED(读操作优化):以非事务方式执行,存在事务则挂起。适合纯查询,避免无谓的事务开销。
如 getPerson()、listProducts() 这类只读方法,加上 @Transactional(propagation = Propagation.NOT_SUPPORTED),既不开启事务,也不干扰上游事务。
NESTED(保存点回滚):当前有事务时,建立保存点(savepoint),子操作失败仅回滚到该点,不影响外层事务。
适用于部分失败可接受的场景,比如批量导入中某条数据格式错误,只跳过该条,其余继续提交。
配置注意事项
propagation 是 @Transactional 的属性之一,需配合其他设置协同使用:
- 搭配 rollbackFor 明确哪些异常触发回滚(默认只响应 RuntimeException)
- 搭配 isolation 控制并发问题(如防止脏读、幻读)
- 搭配 readOnly = true 可让数据库优化执行计划(尤其对 NOT_SUPPORTED 或 SUPPORTS 场景更安全)
- 避免在同一个类中自调用:methodA() 直接调 methodB(),B 的 propagation 不生效,因绕过了代理
验证是否生效的小技巧
启用 Spring 事务调试日志,观察控制台输出:
logging.level.org.springframework.jdbc.support.JdbcTransactionManager=DEBUG
你会看到类似 “Creating new transaction”、“Participating in existing transaction”、“Suspending current transaction” 等提示,对应不同 propagation 行为的实际执行路径。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











