Spring 事务的传播行为有哪几种?分别是什么含义?
结论先行:传播行为解决“事务方法调用另一个事务方法/普通方法”时事务边界如何传递,一共 7 种。记熟“新建系”三兄弟即可应对大多数面试:REQUIRED(默认,有事务就加入、没有就新建)、REQUIRES_NEW(挂起当前事务、另开新事务)、NESTED(嵌套事务,内层失败只回滚到保存点);其余四种 SUPPORTS、NOT_SUPPORTED、MANDATORY、NEVER 属于边界限定。
七种传播行为表
| 传播行为 | 外层有事务 | 外层无事务 | 一句话 |
|---|---|---|---|
| REQUIRED | 加入外层 | 新建事务 | 默认,同生共死 |
| SUPPORTS | 加入外层 | 非事务执行 | 有就蹭、没有就裸跑 |
| MANDATORY | 加入外层 | 抛异常 | 必须在事务里执行 |
| REQUIRES_NEW | 挂起外层、新开 | 新建事务 | 内外各自独立提交 |
| NOT_SUPPORTED | 挂起外层 | 非事务执行 | 强制不开事务 |
| NEVER | 抛异常 | 非事务执行 | 禁止出现事务 |
| NESTED | 保存点嵌套 | 新建事务 | 内层失败只回滚内层 |
代码示例:业务失败也要记录日志
@Service
public class OrderService {
@Transactional
public void placeOrder(Order order) {
save(order); // 主事务:失败则整体回滚
logService.writeLog(order); // REQUIRES_NEW:独立提交,不受主事务影响
}
}
@Service
public class LogService {
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void writeLog(Order order) {
logMapper.insert(order);
}
}
高频坑点
- 同类自调用会绕过代理,传播行为与事务注解一起失效;
- REQUIRES_NEW 内外各占一个数据库连接,连接池过小时可能互相等待甚至耗尽;
- NESTED 依赖 JDBC 保存点能力,不同数据库/驱动支持度有差异。
常见追问 / 记忆点
- 追问:REQUIRES_NEW 与 NESTED 的本质区别?答:前者是完全独立的新事务,内层提交后即使外层回滚也不受影响;后者是保存点机制,内层回滚只回滚到保存点,外层仍可决定整体提交或回滚。
- 追问:默认传播行为与回滚规则?答:REQUIRED,且默认只回滚 RuntimeException 与 Error。
- 记忆点:先记“新建系”三兄弟 REQUIRED/REQUIRES_NEW/NESTED,其余四种当“边界限定系”记。