本文目录导读:

Spring 的事务传播行为(Transaction Propagation)定义了当一个事务方法被另一个事务方法调用时,事务的边界应该如何扩散。
通俗地说,就是解决方法嵌套调用时,是共用同一个事务,还是各自独立事务,或者创建新事务的问题。
Spring 定义了 7种 传播行为(基于 Propagation 枚举),下面逐一说明。
核心分类(以是否支持当前事务为界)
REQUIRED(必须的)— 最常用,默认值
- 行为:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
- 场景:绝大多数业务方法适用。
A.save()调用B.save(),两者应在同一个事务中,要么都成功,要么都回滚。 - 示例:
@Transactional(propagation = Propagation.REQUIRED) public void methodA() { // ... methodB(); // methodB 会使用 methodA 的同一事务 }
SUPPORTS(支持的)
- 行为:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务方式执行。
- 场景:某些查询方法,有事务更好(能读已提交等),没有事务也能跑。
- 注意:非事务环境下执行时,可能导致脏读、不可重复读等问题。
MANDATORY(强制的)
- 行为:必须在现有事务中执行,如果当前没有事务,则直接抛出异常。
- 场景:该方法不允许被没有事务的调用者执行,确保调用方必须开启事务。
- 示例:
@Transactional(propagation = Propagation.MANDATORY)
核心分类(以创建新事务为主)
REQUIRES_NEW(总是新事务)— 常用
- 行为:无论当前是否存在事务,都挂起当前事务,创建一个全新的独立事务。
- 关键点:
- 新事务与外部事务互不影响,外层回滚,内层已提交则不受影响(需捕获异常);内层回滚,外层可以继续提交(除非捕获到内层异常)。
- 场景:
- 日志记录:业务回滚了,但操作日志必须写入(不能因为业务失败而丢失日志)。
- 发消息:业务失败了,但MQ消息已发送,不希望消息也被回滚。
- 示例:
@Transactional public void outer() { inner(); // 如果这里抛出异常,但 inner 已提交,则 outer 回滚不影响 inner } @Transactional(propagation = Propagation.REQUIRES_NEW) public void inner() { ... }
NOT_SUPPORTED(不支持事务)
- 行为:以非事务方式执行,如果当前存在事务,则挂起当前事务。
- 场景:包含一些不需要事务、且可能耗时较长的操作(如批量大文件处理),避免长时间占用数据库连接。
NEVER(绝不)
- 行为:以非事务方式执行,如果当前存在事务,则直接抛出异常。
- 场景:强制要求调用方不能有事务,例如某些必须在无事务环境下执行的清空数据操作(避免自动清空被回滚)。
NESTED(嵌套事务)— 特殊且强大
- 行为:如果当前存在事务,则在嵌套事务内执行(利用数据库的 Savepoint 保存点机制);如果当前没有事务,则行为同
REQUIRED。 - 关键点:
- 不是新事务:内层回滚,可以回滚到嵌套的保存点,不影响外层。
- 外层回滚:内层也一起回滚。
- 前提:数据库必须支持保存点(主流数据库如 MySQL、Oracle 都支持)。
- 与
REQUIRES_NEW的区别:REQUIRES_NEW:内层是独立事务,外层不能看到内层的未提交状态,且内层提交后不受外层影响。NESTED:内层是外层的一部分,外层能看到内层的未提交状态,内层回滚仅回滚到保存点,不结束外层事务。
- 场景:
- 批量操作,部分失败允许跳过:比如批量导入100条数据,第50条失败。
NESTED允许回滚到第50条之前,继续执行第51条;REQUIRES_NEW则第50条失败需要单独处理,且第50条之前的已提交(更复杂)。
- 批量操作,部分失败允许跳过:比如批量导入100条数据,第50条失败。
核心对比表
| 传播行为 | 是否有当前事务 | 行为 | 典型场景 |
|---|---|---|---|
| REQUIRED | 有 | 加入 | 默认选择,方法嵌套共享事务 |
| 无 | 新建 | ||
| SUPPORTS | 有 | 加入 | 查询方法,有事务更好,无事务也行 |
| 无 | 非事务运行 | ||
| MANDATORY | 有 | 加入 | 强制调用方必须有事务 |
| 无 | 抛出异常 | ||
| REQUIRES_NEW | 有 | 挂起当前,新建独立事务 | 日志、审计、消息发送 |
| 无 | 新建 | ||
| NOT_SUPPORTED | 有 | 挂起当前,非事务运行 | 耗时非事务操作 |
| 无 | 非事务运行 | ||
| NEVER | 有 | 抛出异常 | 强制无事务环境 |
| 无 | 非事务运行 | ||
| NESTED | 有 | 嵌套事务(保存点) | 批量处理,部分异常可跳过 |
| 无 | 新建(同REQUIRED) |
实战常见面试点
REQUIREDvsREQUIRES_NEW:前者是“同生共死”;后者是“各管各的”。NESTEDvsREQUIRES_NEW:前者外层回滚内层必回滚;后者外层回滚不影响内层(若内层已提交)。- 事务传播只在方法调用时生效:必须在代理对象(AOP代理,如Spring管理的Bean)之间调用才生效。同类内部方法调用(
this.xxx())不会触发事务传播(因为不走代理)。 - 默认值:
@Transactional不加参数时,默认是REQUIRED。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播