事务注解在哪些情况下失效?

考查重点:代理生效条件与回滚语义。检查是否经 Spring 代理、回滚异常是否匹配、数据库操作是否在同一事务资源内;自调用和吞异常是常见原因

本题目录

参考答案

核心回答

以 Spring Framework 6.2、默认代理模式、普通 JDBC/JPA 本地事务为例,事务注解“失效”通常要分成三类:调用没经过事务增强、回滚条件没满足、操作不在这笔事务的资源范围内。

常见场景有:

  1. 没有通过 Spring 的事务代理调用:对象由自己 new 出来、未启用事务基础设施,或者同一个对象内部直接调用另一个事务方法。自调用绕过代理,被调用方法上的事务属性不会得到这次增强。
  2. 方法不能被当前代理正确拦截:接口代理要求事务方法是代理接口中定义的 public 方法;Spring 6 的类代理默认还能支持 protected、包可见方法,但 private 方法无法这样增强,final 方法也不能被类代理重写增强。不能把“非 public 都失效”套到所有版本和代理类型。
  3. 异常与回滚规则不匹配:默认规则对 RuntimeException、Error 回滚,受检异常默认不回滚;异常被内部捕获并正常返回,拦截器也可能看不到失败。还要检查 rollbackFor、noRollbackFor 和全局默认规则。
  4. 线程或资源边界变了:新线程、异步任务不会自动继承调用线程的本地事务;多数据源时选错事务管理器,或数据库访问没有使用其管理的资源,也不会获得预期的整体回滚。
  5. 传播行为与预期不同:例如 SUPPORTS 在没有外层事务时可以不创建事务,NOT_SUPPORTED 会挂起已有事务。这是配置语义,不能一律当成注解故障。

自调用为什么最容易误判?

假设 placeOrder 直接调用同一对象的 saveOrder,只有后者标了 @Transactional。调用走的是目标对象的 this,不会重新经过代理,因此不会因后者的注解开启事务。更清楚的做法是把完整的事务工作放到独立服务,由调用方通过注入的代理进入,或明确使用编程式事务边界。

但如果 placeOrder 已经通过代理开启事务,saveOrder 使用同一受管理资源时,数据库操作仍可能参与外层事务。此时失去的是 saveOrder 上单独声明的事务语义,例如它声明的 REQUIRES_NEW 不会通过这次自调用生效,不能说里面所有 SQL 必然没有事务。

代理还需要完成初始化,因此不应依赖同一 Bean 的 @PostConstruct 调用触发事务增强。AspectJ 字节码织入模式则不受同样的自调用代理限制,需要与这里讨论的默认模式分开。

为什么抛异常了仍可能不回滚?

先看异常是否越过事务拦截边界,再看匹配到的回滚规则。

默认配置下,业务抛出受检异常,不会仅因为“抛了 Exception”就自动回滚。可以按业务语义配置具体的 rollbackFor;Spring 6.2 也支持把全局默认回滚行为改成 ALL_EXCEPTIONS。因此排查时要看实际配置,不能只背默认值。

如果方法 catch 住异常、返回失败码,且事务没有被标记为 rollback-only,事务可能正常提交。反过来,若内层已把共同事务标为 rollback-only,外层吞掉异常也不代表可以提交,提交时可能收到 UnexpectedRollbackException。catch 与“不回滚”没有无条件对应关系。

线程和事务管理器要怎么查?

普通 PlatformTransactionManager 事务主要绑定当前执行线程。把一部分写入丢给线程池后,原线程回滚不会自动撤销新线程的写入;新线程若通过合适的事务代理进入,可以开启自己的事务,但那是另一笔事务。响应式事务使用 Reactor 上下文,不能直接套用线程绑定的解释。

多数据源场景要确认 transactionManager 指定的管理器、实际执行 SQL 的数据源和连接是否对应。一个普通本地事务也不会自动覆盖另一数据库、HTTP 调用或消息发送。

实际定位可以沿着“调用引用与代理→方法属性→异常经过的边界→所用线程和数据资源”检查,再查看事务开启、参与、提交或回滚日志。验证回滚时,应从事务结束后的独立查询确认数据结果;只看方法返回失败或日志打印异常并不够。

参考资料

相关面经

6 篇

华盛通

Java实习生
实习
查看原面经 →
@Transactional 什么情况下会失效?

极兔速递

后端开发工程师
一面
查看原面经 →
事务注解在什么情况下会失效吗?

蔚来

Java 开发工程师
一面
查看原面经 →
Spring 声明式事务失效的场景

禅游科技

全栈开发工程师
实习一面
查看原面经 →
问redis实现的必要性?说用redis和aop不如直接nacos等,然后转到相关八股,aop实现基于的动态代理,什么情况会aop失效,然后说和事务注解相似,又问我事务失效的情况

亚信科技

Java 开发工程师
实习
查看原面经 →
Java基础:ArrayList、LinkedList、Bean生命周期、Spring事务失效、自动装配、JVM、测试注解等基础知识点
展开剩余 1 篇面经

上海景行智合安全技术

Java 开发工程师
实习一面、二面
查看原面经 →
Spring @Transactional 事务注解失效有哪些场景

相关题目

4 题