踩坑记录
Spring Boot 事务注解失效?我花了一个下午才找到原因
前两天写一个下单逻辑,代码逻辑没问题,单元测试也过了,但一联调就发现——事务压根没生效。
数据该插的插进去了,该回滚的时候也没回滚。
问题重现
java
@Service
public class OrderService {
@Transactional
public void createOrder(OrderDTO dto) {
// 保存订单
orderDao.insert(order);
// 扣减库存 —— 这里抛异常了
inventoryService.decrease(dto.getProductId(), dto.getCount());
}
}简单来说就是:createOrder 方法抛了异常,但前面的订单数据没有回滚。
排查过程
排查了两个方向:
数据库引擎是 InnoDB 吗? 是的,支持事务。
Spring 事务配置有问题? 默认配置,没改动。
最后发现,问题出在 @Transactional 默认只回滚 RuntimeException,而我抛的是一个自定义的 BusinessException,它继承的是 Exception,不是 RuntimeException。
解决方案
改成这样就行了:
java
@Transactional(rollbackFor = Exception.class)
public void createOrder(OrderDTO dto) {
// ...
}加上 rollbackFor = Exception.class,告诉 Spring:“只要抛异常,不管是什么类型,都给我回滚。”
一个小提醒
如果你的 Service 方法被同一个类里的另一个方法调用,@Transactional 也可能失效。因为 Spring 事务是通过代理实现的,内部调用走的是 this,不是代理对象。
解决方法也不复杂:把事务方法抽到单独的 Service 里,或者用 AopContext.currentProxy() 拿到代理对象。
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 程序员小航
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果