Spring @Transactional 注解深度解析
@Transactional
是 Spring 框架中用于声明式事务管理的核心注解,它简化了数据库事务的操作,让开发者能够以声明的方式控制事务边界。以下是该注解的全面解析:
1. 基本用法
java
@Transactional
public void transferMoney(Long fromId, Long toId, BigDecimal amount) {
// 业务逻辑
accountRepository.debit(fromId, amount);
accountRepository.credit(toId, amount);
}
2. 核心属性配置
属性名 | 说明 | 默认值 |
---|---|---|
propagation |
事务传播行为 | REQUIRED |
isolation |
事务隔离级别 | DEFAULT(数据库默认) |
timeout |
事务超时时间(秒) | -1(不超时) |
readOnly |
是否只读事务 | false |
rollbackFor |
触发回滚的异常类型 | RuntimeException和Error |
noRollbackFor |
不触发回滚的异常类型 | 无 |
3. 事务传播行为(Propagation)
java
@Transactional(propagation = Propagation.REQUIRED)
- REQUIRED(默认):如果当前存在事务,则加入该事务;如果不存在,则新建一个事务
- SUPPORTS:如果当前存在事务,则加入该事务;如果不存在,则以非事务方式执行
- MANDATORY:必须在一个已有的事务中执行,否则抛出异常
- REQUIRES_NEW:新建事务,如果当前存在事务,则挂起当前事务
- NOT_SUPPORTED:以非事务方式执行,如果当前存在事务,则挂起当前事务
- NEVER:以非事务方式执行,如果当前存在事务,则抛出异常
- NESTED:如果当前存在事务,则在嵌套事务内执行;否则新建事务
4. 事务隔离级别(Isolation)
java
@Transactional(isolation = Isolation.READ_COMMITTED)
- DEFAULT:使用底层数据库的默认隔离级别
- READ_UNCOMMITTED:读未提交(可能发生脏读、不可重复读和幻读)
- READ_COMMITTED:读已提交(防止脏读,但可能发生不可重复读和幻读)
- REPEATABLE_READ:可重复读(防止脏读和不可重复读,可能发生幻读)
- SERIALIZABLE:串行化(最高隔离级别,防止所有并发问题)
5. 实现原理
Spring 通过 AOP(面向切面编程) 实现 @Transactional
的功能:
-
代理机制:
- 对带有
@Transactional
注解的类/方法,Spring 会生成代理对象 - 使用 JDK 动态代理(基于接口)或 CGLIB(基于类继承)
- 对带有
-
事务拦截器:
TransactionInterceptor
负责拦截方法调用- 在方法执行前开启事务,执行后提交或回滚事务
-
事务管理器:
- 实际事务操作委托给
PlatformTransactionManager
实现 - 如
DataSourceTransactionManager
(JDBC)、JpaTransactionManager
(JPA)等
- 实际事务操作委托给
6. 使用注意事项
-
生效条件:
- 必须作用于 public 方法 上
- 同一个类内部方法调用不会触发事务(因绕过代理)
- 需要配置
@EnableTransactionManagement
(Spring Boot 已自动配置)
-
常见问题:
- 自调用失效:类内部方法A调用方法B,B的事务注解不生效
javapublic class AccountService { public void A() { this.B(); // 事务不生效 } @Transactional public void B() { // ... } }
- 异常捕获:在方法内捕获异常而未重新抛出,会导致事务无法回滚
- 多数据源:需要为每个数据源配置独立的事务管理器
-
最佳实践:
- 明确指定
rollbackFor
属性 - 避免在事务方法中进行远程调用或耗时操作
- 合理设置事务超时时间
- 只读查询使用
readOnly=true
提升性能
- 明确指定
7. 与其他技术的整合
-
与 JPA/Hibernate 整合:
- 配置
JpaTransactionManager
- 事务内会自动处理 Session 的开启和关闭
- 配置
-
与 Spring Data JPA:
- Repository 接口方法默认已有
@Transactional
- 自定义方法可覆盖默认事务配置
- Repository 接口方法默认已有
-
分布式事务:
- 对于跨库/跨服务场景,可结合 JTA 或 Seata 等分布式事务解决方案
@Transactional
本身不支持跨数据源事务
@Transactional
注解极大简化了事务管理,但理解其底层机制对于处理复杂事务场景至关重要。合理配置传播行为和隔离级别,可以解决大多数并发数据访问问题。