Spring 的事务传播行为(Propagation)用于定义在当前方法被调用时,是否要 开启新事务,还是使用已有事务。这是控制事务嵌套、事务边界的关键。
🔁 Spring 事务传播级别一览(共 7 种)
传播行为(枚举) | 含义 |
---|---|
REQUIRED (默认) | 如果当前有事务,则加入;没有则新建一个事务 ✅ 常用 |
REQUIRES_NEW | 始终新建一个事务,暂停外部事务 |
NESTED | 如果当前有事务,则在当前事务中嵌套(使用保存点);否则新建事务 |
SUPPORTS | 如果当前有事务,则参与;没有就非事务方式运行 |
NOT_SUPPORTED | 总是以非事务方式运行,挂起当前事务 |
NEVER | 当前存在事务时抛异常 |
MANDATORY | 当前必须有事务,否则抛异常 |
📘 实战示例
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void saveNewUser(User user) {
userRepository.save(user);
}
✅ 推荐使用场景
传播级别 | 推荐使用场景 |
---|---|
REQUIRED | 大多数业务方法(默认) |
REQUIRES_NEW | 写操作独立提交,不影响主事务(如日志记录) |
NESTED | 出错时回滚当前操作但不影响主事务(依赖数据库支持保存点) |
SUPPORTS | 查询类操作、工具方法,可有可无事务 |
NOT_SUPPORTED | 调用第三方服务、耗时操作等不希望参与事务 |
MANDATORY | 强制在事务中调用(比如必须由主业务控制) |
🎯 多事务传播执行示意图
假设:ServiceA 调用 ServiceB
ServiceA @Transactional(REQUIRED)
ServiceB @Transactional(REQUIRES_NEW)
效果:ServiceA 的事务和 ServiceB 的事务完全独立,ServiceB 的提交或回滚不会影响 ServiceA。
🧠 实用小贴士
- Spring 事务传播机制底层依赖的是
TransactionManager
和 AOP 代理机制。 - 对于
REQUIRES_NEW
和NESTED
,注意 数据源是否支持嵌套事务或保存点(如 JDBC + MySQL 默认支持)。 - 嵌套事务不等于独立事务,它是依附于外层事务的一部分,只有在外层不回滚时才提交。
🔄 示例代码片段
@Service
public class OrderService {
@Autowired
private PaymentService paymentService;
@Transactional
public void createOrder() {
// 使用默认的 REQUIRED
orderRepository.save(...);
// 独立事务处理支付,不影响订单主事务
paymentService.pay(); // pay() 使用 REQUIRES_NEW
}
}
@Service
public class PaymentService {
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void pay() {
paymentRepository.save(...);
// throw new RuntimeException(); // 只影响 pay,不影响上层
}
}