ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Spring 中事务失效的场景有哪些

Spring 中事务失效的场景有哪些

1、异常捕获处理,自己处理了异常,没有抛出

Spring 事务回滚是由TransactionInterceptor在捕获到业务方法向外抛出的异常后触发的。如果在业务里try-catch把异常吃掉了、没有重新抛出,拦截器就感知不到异常,会走 commit 分支导致事务失效。

以下是由于异常捕获处理导致的事务失效的场景与修复

try-catch 完全吞掉异常

try { doSomething(); } catch (Exception e) { log.error("转账失败", e); } // 拦截器看不到异常 → 提交

应该修复为:

@Transactional public void transfer(...) { try { doSomething(); } catch (Exception e) { log.error("转账失败", e); throw new BizException("转账失败", e); // 必须抛 } }

2、抛出检查异常

默认只回滚 RuntimeException(运行时异常,非受检异常),受检异常需要配置rollbackFor = Exception.class。

受检查异常默认不回滚

@Transactional // 默认只回滚 RuntimeException / Error public void doSomething() throws IOException { throw new IOException("IO错误"); // 受检异常,默认不回滚! }

应该修复为:

@Transactional(rollbackFor = Exception.class) // 显式指定 public void doSomething() throws IOException { throw new IOException("IO错误"); }

3、非 public 方法导致的事务失效

@Transactional只对public方法生效。如果标注在private、protected或包级(default)方法上,Spring 会静默忽略该注解——不报错,但方法完全没有事务能力。

失效案例:调用createOrder时:数据照插,异常照抛,但事务从未开启。

@Service public class OrderService { @Autowired private OrderMapper orderMapper; @Transactional private void createOrder(Order order) { // ❌ private → 事务不生效 orderMapper.insert(order); // 抛异常也不会回滚 throw new RuntimeException("测试"); } }

解决方案:直接把方法改为 public

@Transactional public void createOrder(Order order) { orderMapper.insert(order); }
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进