尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

@Transactional 原理与事务失效场景

@Transactional 原理与事务失效场景
📅 发布时间:2026/7/15 20:44:54

一句话

@Transactional 基于 AOP 动态代理,通过 TransactionInterceptor 在方法前后开启/提交/回滚事务。自调用绕过代理、异常被吞、非 public 方法等 6 个场景会导致事务失效。


1. 底层原理

Controller 调用 userService.save() ↓ 实际调用的是 userService 的代理对象(AOP 动态代理生成的) ↓ 代理对象先走 TransactionInterceptor(事务拦截器) ↓ ① 开启事务(从连接池拿连接 → conn.setAutoCommit(false)) ↓ ② 执行真实方法 save() ↓ ③ 正常结束 → commit() 抛异常 → rollback()

三个核心角色:

角色职责
PlatformTransactionManager事务管理器,负责 begin / commit / rollback
TransactionInterceptor事务拦截器,AOP 切面的具体执行者
@Transactional标记注解,告诉 Spring 哪些方法需要事务增强

PlatformTransactionManager 由 Spring Boot 自动配置创建(引入 DataSource + spring-tx 依赖即可)。


2. 事务失效的 6 个高频场景

场景 1:自调用(最常考)

@ServicepublicclassUserService{@TransactionalpublicvoidmethodA(){// 操作数据库...this.methodB();// ← this 调用,绕过代理对象}@TransactionalpublicvoidmethodB(){// 操作数据库...}}

this.methodB()调用的是原始对象,不是代理对象,TransactionInterceptor 没机会拦截。

解决:

① 把 methodB 抽到另一个 Service 类(走代理) ② 注入自己:@Autowired private UserService self; self.methodB();

场景 2:方法不是 public

@Transactionalprivatevoidsave(){// Spring AOP 只拦截 public 方法// 操作数据库}

场景 3:异常被 catch 吞掉

@Transactionalpublicvoidsave(){try{// 操作数据库}catch(Exceptione){log.error("出错了",e);// 异常被吞,代理以为正常结束,走 commit}}

代理对象只会在方法抛异常时触发 rollback。catch 吞了异常,代理不知道出错了。

解决:catch 里重新 throw,或手动标记回滚:

TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

场景 4:异常类型不匹配

@Transactional// 默认 rollbackFor = RuntimeExceptionpublicvoidsave()throwsIOException{thrownewIOException("文件错误");// 检查异常,不回滚}

默认只对 RuntimeException 和 Error 回滚。IOException、SQLException 等检查异常不会触发回滚。

解决:@Transactional(rollbackFor = Exception.class)

场景 5:类没交给 Spring 管理

publicclassUserService{// 没有 @Service@Transactionalpublicvoidsave(){// 自己 new 出来的对象没有代理对象}}

场景 6:传播级别不对

@Transactional(propagation=Propagation.NOT_SUPPORTED)publicvoidsave(){// 明确说了不支持事务}

3. 传播级别 vs 隔离级别

面试容易混的两个概念:

传播级别 propagation:这个方法和已有事务是什么关系 REQUIRED(默认):有事务就加入,没有就新建 REQUIRES_NEW:挂起已有事务,新建独立事务 NOT_SUPPORTED:明确不要事务 SUPPORTS:有事务就加入,没有就非事务执行 MANDATORY:必须在事务中调用,否则抛异常 NEVER:必须不在事务中调用,否则抛异常 NESTED:嵌套事务(子事务回滚不影响父事务) 隔离级别 isolation:事务之间互相隔离的程度 READ_UNCOMMITTED → 脏读 READ_COMMITTED → 不可重复读(MySQL 默认) REPEATABLE_READ → 幻读(InnoDB 默认) SERIALIZABLE → 串行化

传播级别影响"事务是否生效",隔离级别影响"并发读写是否安全"。不要混。


4. @Transactional 常用属性

@Transactional(propagation=Propagation.REQUIRED,// 传播级别isolation=Isolation.DEFAULT,// 隔离级别(用数据库默认)timeout=30,// 超时秒数readOnly=false,// 是否只读rollbackFor=Exception.class,// 指定回滚异常类型noRollbackFor=NullPointerException.class// 指定不回滚异常类型)

面试回答模板

"@Transactional 底层基于 AOP 动态代理。调用带 @Transactional 注解的方法时, 实际执行的是代理对象,代理对象通过 TransactionInterceptor 在方法前开启事务, 方法正常结束 commit,抛异常 rollback。 事务失效最常见的是自调用:同一个类里 this.method() 绕过了代理对象, TransactionInterceptor 没机会拦截,事务不生效。 其他常见场景包括:方法不是 public、异常被 catch 吞掉、 异常类型不匹配(默认只回滚 RuntimeException)、 类没交给 Spring 管理、传播级别设为 NOT_SUPPORTED。 这里要注意传播级别和隔离级别是两个不同概念: 传播级别控制方法和已有事务的关系,隔离级别控制并发读写的隔离程度。"

参考来源

  • Day11-Spring 与 SpringBoot
  • 01_Raw【原始素材】/面试资料-B站博主/Spring篇(13题) - 飞书云文档.md

相关新闻

  • Java NIO内存管理机制剖析
  • 效率的馈赠与创意的觉醒:AI时代的人文主义复兴
  • MMDetection(简称 mmdet)是 OpenMMLab 开发的开源目标检测框架,基于 PyTorch 构建

最新新闻

  • 万物的骨架:深入理解 Mesh(网格)
  • Istio 到 Cilium Service Mesh 的迁移评估:eBPF 能否替代 Sidecar
  • 北京急出邮票纪念币不用等!全域快速上门回收,当场结清全款 - 深鉴新闻
  • 在深圳遇到这8种情况,不用犹豫,直接找无忧白蚁 - GrowthUME
  • 机器学习特征预处理之分类缺失填充
  • Android随笔-Context

日新闻

  • 告别启动盘残留:用Diskpart彻底清除U盘EFI分区与恢复完整空间
  • 2026 年宜春诚信的塑料缠绕膜厂家哪个好,缠绕膜背后的秘密:你不知道的成本陷阱 - 领域鉴赏官
  • Arch ECS 入门指南:10分钟掌握C#高性能数据驱动架构

周新闻

  • IX9104 PCIe5.0 高速交换芯片@ACP#完整规格 + 应用场景总结
  • Unity游戏集成Coze智能体:实现NPC智能对话与知识库联动
  • SAP EPIC 建行回单查询:从标准类CL_EPIC_EXAMPLE_CN_CCB_GHTD到Z类的5处关键修改

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号