1. 先分三个层级,从上到下
第一层:数据库本身的事务(MySQL 事务)
这是底层原生 的,和 Java、Spring 一毛钱关系都没有。MySQL 自己就有事务:begin; → 开启insert/update/delete``commit; → 提交rollback; → 回滚
特点:
- 数据库自己管提交、回滚
- 开启事务后,不提交、不回滚,连接就一直被占用
- 持有行锁、表锁
- 一条 SQL 执行完默认自动提交(autocommit=on)
你可以理解为:仓库本身自带的锁机制。
第二层:Java 程序里的事务
Java 只是调用数据库 ,Java 本身没有事务!Java 只是通过 JDBC 告诉 MySQL:
- 你给我开事务
- 执行 SQL
- 最后统一提交 / 统一回滚
JDBC 事务本质就是:控制数据库事务的开关
java
// JDBC原生伪代码
connection.setAutoCommit(false); // 关闭自动提交 = 开启事务
// 执行一堆sql
connection.commit(); // 全部成功才提交
connection.rollback(); // 任意失败全部回滚
所以:Java 没有事务,Java 只是操控数据库事务
第三层:Spring AOP 切面事务(@Transactional)
这就是你天天用的,也是最绕的一层。
Spring 做了一件事:用 AOP 动态代理 + 切面,自动帮你管理 JDBC 事务
流程是:
- 你在方法上加
@Transactional - Spring 的事务切面拦截这个方法
- 方法执行前:自动开启数据库事务(关闭 autoCommit)
- 执行你写的业务代码(循环、mapper、接口调用)
- 方法全部正常结束:自动 commit 提交
- 方法抛异常:自动 rollback 回滚
一句话总结
@Transactional 就是 Spring AOP 切面切面 = 拦截器自动帮你开关数据库事务。
2. 三者完整关系链(核心图)
plaintext
Spring AOP事务切面
↓
控制 Java JDBC 事务
↓
操控 MySQL 数据库原生事务
- 数据库事务:底层能力
- Java JDBC:中间桥梁,发指令给数据库
- Spring AOP 切面:自动帮你套事务,不用手写开关
2.1 @Transactional 的传播行为
| 传播行为 | 含义 | 核心一句话 |
|---|---|---|
| REQUIRED(默认) | 如果外层有事务,就加入当前事务;没有则新建事务 | 有就共用,没有就新建 |
| SUPPORTS | 外层有事务,就加入;没有事务,就无事务执行 | 有就用,没有就裸跑 |
| MANDATORY | 外层必须存在事务,没有直接抛异常 | 必须外层有事务,否则报错 |
| REQUIRES_NEW | 挂起外层事务,创建全新独立事务;内外事务互不影响 | 挂起旧的,开全新事务 |
| NOT_SUPPORTED | 挂起外层事务,以无事务运行;执行完恢复外层事务 | 挂起旧事务,强制裸跑 |
| NEVER | 绝对不允许外层存在事务;外层有事务直接抛出异常 | 有事务直接报错 |
| NESTED | 外层有事务,则在当前事务内创建保存点 (savepoint);外层无事务则新建事务 | 嵌套事务,支持局部回滚 |
3. 问题回答
问题 1:Java 有事务吗?
**没有。**Java 只是操控数据库事务。
问题 2:@Transactional 是什么?
Spring AOP 切面。专门用来自动管理数据库事务的切面。
问题 3:切面和事务是什么关系?
切面 = 事务的管理者 不加注解 → 切面不理你加默认注解 → 切面全程托管事务加 NOT_SUPPORTED → 切面完全不管,放开你
问题 4:为什么定时任务一定要 NOT_SUPPORTED?
定时任务特点:
- 长循环
- 大量数据库操作
- 调用外部接口、流程引擎(慢 IO)
- 不需要多 SQL 统一回滚
完全不需要统一事务,所以直接关掉切面托管。
问题 5:程序运行数据库是不是会停止?
**完全不是!**数据库一直正常运行。只是不加注解时:连接被切面开启的长事务占住,别人用不了。
问题 6:什么时候需要 @Transactional 默认事务?
普通业务接口 比如:下单、扣款、入库、修改多条 SQL 必须一起成功、一起失败,不能中途提交。
问题 7:什么时候必须关掉事务(NOT_SUPPORTED)?
- 定时任务
- 异步任务
- 后台批处理
- 循环大量操作
- 方法内包含网络调用、第三方接口
- 不需要统一回滚的场景
4. 背诵口诀
- 事务本身是数据库的,Java 没有事务
- @Transactional 是 Spring AOP 切面,自动管数据库事务
- 默认切面:方法全程一个大事务,跑完才提交
- NOT_SUPPORTED:取消切面管理,无事务,每条 SQL 自动提交
- 定时任务必须关闭切面