@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

✅ 不在新线程中操作事务

相关推荐
程序员阿明2 小时前
flowable集成flowable及其运行示例spring boot后端
java·spring boot·后端
努力发光的程序员2 小时前
面试官与程序员谢飞机的3轮Java大厂面试问答实录:涵盖Spring Boot、微服务与数据库技术
java·jvm·spring boot·redis·面试·hibernate·microservices
zoyation3 小时前
Spring Boot多数据源
java·spring boot·后端
i220818 Faiz Ul3 小时前
在线预约导游|基于SSM+vue的在线预约导游系统(源码+数据库+文档)
java·前端·数据库·vue.js·spring boot·毕设·在线预约导游系统
绝知此事3 小时前
ELK 从入门到精通:Spring Boot 实战三部曲(二)—— 进阶特性与性能优化
spring boot·elk·性能优化
绝知此事3 小时前
ELK 从入门到精通:Spring Boot 实战三部曲(一)—— 基础核心与快速上手
spring boot·后端·elk
MaCa .BaKa3 小时前
56-非遗手工艺品定制平台系统
java·vue.js·spring boot·mysql·maven·非遗手工制作平台系统·非遗制作
莫寒清3 小时前
@CrossOrigin 注解
java·spring boot·后端
憧憬成为java架构高手的小白14 小时前
苍穹外卖--day09
java·spring boot·百度