@Transactional失效场景

一、一句话结论(面试开场必说 ⭐⭐⭐⭐⭐)

@Transactional 本质是 Spring AOP 动态代理,只要事务方法没有被 Spring 代理调用,就会失效。

二、@Transactional 失效的 10 大场景(重点 ⚠️)

✅ 1️⃣ 同类方法调用(最常见 ❌)

@Service

public class UserService {

复制代码
public void outer() {
    inner(); // ❌ 事务失效
}

@Transactional
public void inner() {}

}

❌ 原因

• 调用的是 this.inner()

• 绕过了 Spring 代理

✅ 解决

• 拆到另一个 Service

• 或通过代理对象调用

✅ 2️⃣ 方法是 private(❌ 直接失效)

@Transactional

private void save() {}

❌ 原因

• Spring AOP 是基于代理实现的,private 方法无法被代理类重写或拦截,因此不能被增强。

✅ 正确写法

@Transactional

public void save() {}

✅ 3️⃣ 方法是 final / static(❌)

@Transactional

public final void save() {}

❌ 原因

• CGLIB 无法重写 final 方法

• static 不属于对象

✅ 4️⃣ 异常被 catch 吃掉(❌)

@Transactional

public void save() {

try {

int i = 1 / 0;

} catch (Exception e) {

// ❌ 不抛异常 = 不回滚

}

}

✅ 正确

catch (Exception e) {

throw e;

}

✅ 5️⃣ 抛出的异常不是 RuntimeException(❌)

@Transactional

public void save() throws Exception {

throw new Exception(); // ❌ 默认不回滚

}

✅ 解决

@Transactional(rollbackFor = Exception.class)

✅ 6️⃣ 传播行为设置错误(❌)

@Transactional(propagation = Propagation.NOT_SUPPORTED)

public void save() {}

❌ 原因

• 非事务方式执行

✅ 7️⃣ 数据库引擎不支持事务(❌)

数据库 引擎

MySQL ❌ MyISAM

MySQL ✅ InnoDB

📌 MyISAM 不支持事务

✅ 8️⃣ 未开启事务注解(❌)

// ❌ 忘了加

@EnableTransactionManagement

或 Spring Boot 未引入:

spring-tx

✅ 9️⃣ 多线程调用(❌)

@Transactional

public void parent() {

new Thread(() -> child()).start();

}

❌ 原因

• Spring 事务 绑定线程

• 子线程无事务

✅ 🔟 非 Spring 管理的 Bean(❌)

new UserService().save(); // ❌ 不在容器中

✅ 必须是:

@Autowired

UserService userService;

三、一张表彻底记住(面试救命表 ⭐⭐⭐⭐⭐)

场景 是否失效
同类方法调用
private 方法
final 方法
异常被 catch
非 RuntimeException
NOT_SUPPORTED
MyISAM
多线程
非 Spring Bean

四、面试标准回答(背这段 ✅)

@Transactional 失效主要是因为 Spring 事务基于 AOP 动态代理,常见场景包括:同类方法调用、private/final 方法、异常被捕获、异常类型不匹配、传播行为错误、数据库不支持事务、多线程调用以及 Bean 未被 Spring 管理。

五、如何快速排查事务是否生效?

✅ 1️⃣ 看日志

Creating new transaction with name ...

✅ 2️⃣ 强制异常测试

throw new RuntimeException("test");

✅ 3️⃣ 打印代理对象

System.out.println(AopContext.currentProxy());

六、最佳实践(强烈建议 ✅)

✅ 事务方法 public

✅ 不在同类中调用

✅ 明确 rollbackFor = Exception.class

✅ 不吞异常

✅ 不使用 MyISAM

✅ 不在新线程中操作事务

相关推荐
Flynt6 小时前
把公司项目迁到 Spring Boot 4.0:编译通过只是开始
java·spring boot·后端
yxlalm8 小时前
5.3解决超卖问题
java·spring boot·超卖
边境悍匪10 小时前
蜗牛学苑 Java 智能体学习 Day39|SpringAI 会话存储、Function‑Call 工具调用、MCP 思维导图复盘
java·开发语言·spring boot·学习·阿里云
xcl092512 小时前
全民健身智慧管理系统实战指南:从架构设计到部署落地
java·spring boot
Bs_MoneyMagnet12 小时前
基于springboot+vue的宠物殡葬管理平台的设计与实现 源码+文档
java·javascript·vue.js·spring boot·后端·宠物
ly768912 小时前
生产环境 Spring Boot 应用内存泄漏排查实战
java·spring boot·spring·内存泄漏·threadlocal·gc日志·堆转储
行百里er13 小时前
Spring Insight 里上报 Span 为什么用 JDK HttpClient 而不是 RestTemplate
spring boot·spring cloud·监控
Bs_MoneyMagnet14 小时前
基于springboot+vue的家居生活商城平台的设计与实现 源码+文档
java·vue.js·spring boot·后端·spring
微三云 - 廖会灵 (私域系统开发)14 小时前
Spring Boot实战:五级分销定价与自动分佣系统设计与实现
java·spring boot·后端
风中的小熊生气15 小时前
Spring Boot 面试知识(一):从启动流程到 AOP 与事务失效
spring boot·后端·面试