Transactional注解详解

目录

一、什么是 @Transaction(al) 注解

在 Spring Framework 中,@Transactional 是用于声明式事务管理的核心注解。

👉 本质作用:

让方法在执行时自动具备事务能力(开启事务 → 执行 → 提交 / 回滚)

一个直观例子

1
2
3
4
5
6
7
8
9
@Service
public class UserService {

@Transactional
public void transfer() {
// 1. 扣钱
// 2. 加钱
}
}

执行逻辑:

  1. 开启事务
  2. 执行 transfer()
  3. 如果正常 → 提交事务 ✅
  4. 如果抛异常 → 回滚事务 ❌

二、作用范围

@Transactional 可以作用于:

  • 方法:推荐将注解使用于方法上,不过需要注意的是:该注解只能应用到public方法上,否则不生效
  • 类:作用于类上时,表示该类的所有 public 方法都具有事务功能
  • 接口:不推荐,接口上的注解不会被实现类继承

三、底层原理(面试重点)

3.1 核心机制:AOP

@Transactional 是基于 Spring AOP 实现的。

👉 执行流程:

1
调用方法 → 进入代理对象 → 开启事务 → 调用目标方法 → 提交/回滚 → 返回

3.2 事务管理器(TransactionManager)

Spring 会根据配置选择不同实现:

类型 适用场景
DataSourceTransactionManager JDBC
JpaTransactionManager JPA
HibernateTransactionManager Hibernate

👉 本质:

事务管理器 = 真正控制提交 / 回滚的人

3.3 为什么必须是 public 方法?

👉 因为 Spring AOP 默认使用 动态代理

  • JDK 动态代理 → 只代理接口方法
  • CGLIB → 代理类,但仍有限制

📌 结论:

非 public 方法不会被代理 → 事务失效


四、核心属性(高频面试)🔥

4.1 propagation(传播行为)

控制事务如何传播

含义
REQUIRED(默认) 有就用,没有就新建
REQUIRES_NEW 新开事务,挂起旧事务
SUPPORTS 有就用,没有就不用
NOT_SUPPORTED 强制非事务执行
MANDATORY 必须有事务
NEVER 必须没有事务

4.2 isolation(隔离级别)

对应数据库事务隔离级别:

级别 问题
READ_UNCOMMITTED 脏读
READ_COMMITTED 不可重复读
REPEATABLE_READ 幻读
SERIALIZABLE 最严格

4.3 rollbackFor(回滚规则)

默认:

1
只对 RuntimeException 回滚

👉 自定义:

1
@Transactional(rollbackFor = Exception.class)

4.4 timeout / readOnly

属性 作用
timeout 超时自动回滚
readOnly 只读优化(提高性能)

五、常见坑(面试杀手)⚠️

❌ 1. 同类方法调用失效

1
2
3
4
5
6
public void A() {
B(); // ❌ 事务不会生效
}

@Transactional
public void B() {}

👉 原因:

没走代理对象(this调用)

❌ 2. 捕获异常不抛出

1
2
3
4
5
6
7
8
@Transactional
public void test() {
try {
int i = 1 / 0;
} catch (Exception e) {
// ❌ 吞掉异常,不回滚
}
}

👉 解决:

1
throw e;

❌ 3. 非 public 方法

1
2
@Transactional
private void test() {} // ❌ 无效

❌ 4. 数据库不支持事务

比如:

  • MyISAM ❌(不支持事务)
  • InnoDB ✅

六、执行流程总结(必背)

1
2
3
4
5
6
7
8
9
10
11
12
13
@Transactional 方法调用

进入 AOP 代理

事务管理器开启事务

执行目标方法

是否异常?
↓ ↓
正常 异常
↓ ↓
提交事务 回滚事务

七、面试总结(高频八股)

⭐ 核心一句话

@Transactional 是 Spring 基于 AOP 实现的声明式事务管理,通过事务管理器控制事务的开启、提交和回滚。

⭐ 高频面试问题

@Transactional 为什么会失效?

  • 方法不是 public
  • 同类调用(未走代理)
  • 异常被吞
  • 数据库不支持事务

Spring 事务是如何实现的?

👉 回答模板:

Spring 通过 AOP 为目标方法创建代理,在方法执行前开启事务,执行后根据是否发生异常决定提交或回滚。

事务传播行为最常用的是哪个?

👉 REQUIRED(默认)

rollbackFor 为什么重要?

👉 因为默认只回滚 RuntimeException