Spring事务管理深度解析:原理、实践与陷阱
一、事务基础概念
ACID原则
- 原子性(Atomicity):事务内的操作要么全部成功,要么全部回滚
- 一致性(Consistency):事务前后数据库状态保持一致
- 隔离性(Isolation):并发事务间相互隔离
- 持久性(Durability):事务提交后数据永久存储
二、Spring事务核心接口
public interface PlatformTransactionManager {
TransactionStatus getTransaction(TransactionDefinition definition);
void commit(TransactionStatus status);
void rollback(TransactionStatus status);
}
public interface TransactionDefinition {
int getIsolationLevel();
int getPropagationBehavior();
int getTimeout();
boolean isReadOnly();
}
三、事务配置方式
1. 声明式事务(推荐)
<tx:annotation-driven transaction-manager="txManager"/>
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
@Configuration
@EnableTransactionManagement
public class AppConfig {
@Bean
public PlatformTransactionManager transactionManager(DataSource ds) {
return new DataSourceTransactionManager(ds);
}
}
2. 编程式事务
transactionTemplate.execute(status -> {
try {
userDao.update(user1);
logDao.insert(log);
return true;
} catch (Exception e) {
status.setRollbackOnly();
return false;
}
});
四、@Transactional详解
属性配置
@Transactional(
propagation = Propagation.REQUIRED,
isolation = Isolation.READ_COMMITTED,
timeout = 30,
readOnly = false,
rollbackFor = {BusinessException.class},
noRollbackFor = {SystemException.class}
)
public void businessMethod() { ... }
传播行为(Propagation)
行为类型 |
说明 |
REQUIRED(默认) |
存在事务则加入,没有则新建 |
REQUIRES_NEW |
总是新建事务,挂起当前事务 |
NESTED |
嵌套事务,使用保存点实现部分回滚 |
SUPPORTS |
存在事务则加入,没有则以非事务运行 |
NOT_SUPPORTED |
非事务执行,挂起当前事务 |
MANDATORY |
必须存在事务,否则抛异常 |
NEVER |
必须非事务执行,否则抛异常 |
隔离级别(Isolation)
级别 |
脏读 |
不可重复读 |
幻读 |
说明 |
READ_UNCOMMITTED |
✓ |
✓ |
✓ |
最低隔离级别 |
READ_COMMITTED(默认) |
× |
✓ |
✓ |
避免脏读 |
REPEATABLE_READ |
× |
× |
✓ |
MySQL默认级别 |
SERIALIZABLE |
× |
× |
× |
最高隔离级别 |
五、事务失效场景
- 非public方法:基于代理的AOP无法拦截private方法
- 自调用问题:类内部方法调用不会经过代理对象
解决方案:@Autowired
private ApplicationContext context;
public void methodA() {
context.getBean(ThisClass.class).methodB();
}
- 异常类型不匹配:默认只回滚RuntimeException和Error
- 多线程调用:不同线程属于不同事务上下文
- 错误捕获异常:catch后未重新抛出
try { ... }
catch (Exception e) {
}
六、高级特性
1. 事务同步
TransactionSynchronizationManager.registerSynchronization(
new TransactionSynchronization() {
@Override
public void afterCommit() {
}
});
2. 多数据源事务
@Bean
@Primary
public PlatformTransactionManager primaryTM(DataSource ds1) {
return new DataSourceTransactionManager(ds1);
}
@Bean
public PlatformTransactionManager secondaryTM(DataSource ds2) {
return new DataSourceTransactionManager(ds2);
}
@Transactional(transactionManager = "secondaryTM")
public void crossDatabaseOp() {...}
七、最佳实践
- 事务方法保持简短,避免远程调用
- 明确指定rollbackFor属性
- 只读查询添加@Transactional(readOnly=true)
- 嵌套事务使用PROPAGATION_NESTED
- 监控事务执行时间(超过3秒需优化)