Spring 事务失效的 8 种场景
📺 配套视频
📝 知识点总结
8 种事务失效场景
| # | 场景 | 原因 | 解决方案 |
|---|---|---|---|
| 1 | 方法不是 public | Spring AOP 只能代理 public 方法 | 改为 public |
| 2 | 自调用(this 调用) | 绕过了代理对象,直接调用目标方法 | 注入自身 / AopContext.currentProxy() |
| 3 | 异常被 catch 吞掉 | Spring 感知不到异常,不会回滚 | 抛出异常或手动 setRollbackOnly() |
| 4 | 抛出非 RuntimeException | 默认只回滚 RuntimeException | @Transactional(rollbackFor = Exception.class) |
| 5 | 数据库引擎不支持事务 | MyISAM 不支持事务 | 使用 InnoDB |
| 6 | 没有被 Spring 管理 | 类没加 @Service/@Component | 确保 Bean 在容器中 |
| 7 | 传播行为设置错误 | REQUIRES_NEW 内层事务独立提交 | 根据业务选择正确的传播行为 |
| 8 | 多线程调用 | 事务绑定在 ThreadLocal 上,新线程无事务 | 避免在事务方法中开新线程 |
最容易踩坑的:自调用
@Service
public class OrderService {
// ❌ 事务不生效!this 调用绕过了代理
public void createOrder() {
this.saveOrder(); // 直接调用,不走代理
}
@Transactional
public void saveOrder() {
// 数据库操作
}
}
@Service
public class OrderService {
@Autowired
private OrderService self; // 注入代理对象
// ✅ 通过代理对象调用,事务生效
public void createOrder() {
self.saveOrder();
}
@Transactional(rollbackFor = Exception.class)
public void saveOrder() {
// 数据库操作
}
}
🔗 延伸阅读
- 企业级多数据源事务中间件 — 深入 Spring 事务源码,二次开发多数据源事务