Spring 事务管理是 Spring 框架的核心功能之一,旨在简化数据库事务的复杂性,保障数据一致性和业务逻辑的正确性。以下是 Spring 事务的详细解析,涵盖核心概念、配置方式、实战案例及常见问题。
一、Spring 事务的核心概念
1. 事务的 ACID 特性
- 原子性(Atomicity):事务中的多个操作要么全部成功,要么全部失败。
- 一致性(Consistency):事务执行前后,数据库处于一致状态。
- 隔离性(Isolation):多个并发事务之间互不干扰。
- 持久性(Durability):事务提交后,数据永久保存。
2. Spring 事务管理机制
- 声明式事务:通过
@Transactional
注解声明事务边界(最常用)。 - 编程式事务:通过
TransactionTemplate
或PlatformTransactionManager
手动控制事务。 - 事务管理器(TransactionManager):核心组件,负责事务的创建、提交和回滚。
二、Spring 事务配置
1. 声明式事务配置
@Configuration
@EnableTransactionManagement // 启用事务管理
public class TransactionConfig {
@Bean
public DataSourceTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
2. 使用 @Transactional
注解
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@Transactional // 自动管理事务
public void createUser(User user) {
userRepository.save(user); // 1. 保存用户
sendWelcomeEmail(user.getEmail()); // 2. 发送邮件(可能抛出异常)
}
private void sendWelcomeEmail(String email) {
// 模拟邮件发送失败
if (Math.random() < 0.5) {
throw new RuntimeException("邮件发送失败");
}
}
}
注:
@Transactional 是基于 AOP 实现的,AOP ⼜是使⽤动态代理实现的。如果⽬标对象实现了接⼝,默 认情况下会采⽤ JDK 的动态代理,如果⽬标对象没有实现了接⼝,会使⽤ CGLIB 动态代理。 @Transactional 在开始执⾏业务之前,通过代理先开启事务,在执⾏成功之后再提交事务。如果中途 遇到的异常,则回滚事务。
3. 编程式事务示例
@Service
public class UserService {
@Autowired
private PlatformTransactionManager transactionManager;
@Autowired
private UserRepository userRepository;
public void createUserProgrammatically(User user) {
TransactionDefinition def = TransactionDefinition.withDefaults();
TransactionStatus status = transactionManager.getTransaction(def);
try {
userRepository.save(user);
sendWelcomeEmail(user.getEmail());
transactionManager.commit(status); // 提交事务
} catch (Exception e) {
transactionManager.rollback(status); // 回滚事务
throw e;
}
}
}
三、事务的传播行为
事务传播行为定义了事务在方法调用链中的传播规则,是 Spring 事务管理的核心难点。常见传播行为包括:
传播行为 | 说明 |
---|---|
REQUIRED (默认) |
如果当前没有事务,创建新事务;如果已有事务,加入现有事务。 |
|
支持事务(如果有),否则以非事务方式执行。 |
MANDATORY |
必须存在事务,否则抛出 IllegalTransactionStateException 。 |
REQUIRES_NEW |
创建新事务,无论当前是否存在事务。已存在事务会被挂起(需手动回滚)。 修饰的内部⽅法会新开启⾃⼰的事务,且开启的事务相互独⽴,互不⼲扰 |
NOT_SUPPORTED |
以非事务方式执行,如果当前存在事务则挂起。 |
NEVER | 以非事务方式运行,如果当前存在事务,则抛出异常 |
NESTED |
支持嵌套事务(如 Spring Data JPA 的 @Transactional 默认行为)。 |

示例代码
@Service
public class UserService {
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void createOrder(Order order) {
// 新事务,独立于外部事务
}
@Transactional(propagation = Propagation.NESTED)
public void placeOrder(User user, Order order) {
userRepository.save(user); // 外部事务
createOrder(order); // 嵌套事务
}
}
四、事务的隔离级别
隔离级别用于解决并发事务之间的干扰问题,如脏读、不可重复读、幻读。
隔离级别 | 说明 |
---|---|
DEFAULT |
使用数据库默认隔离级别 |
READ_UNCOMMITTED |
读未提交,可以读取到未提交的事物,但存在脏读 |
READ_COMMITTED |
读已提交,只能读取到已提交的事物,防止脏读,但存在不可重复读 |
REPEATABLE_READ |
可重复读,防止脏读和不可重复读,但存在幻读 |
SERIALIZABLE |
可串行化,防止所有问题(但性能最低) |
配置隔离级别
@Transactional(isolation = Isolation.READ_COMMITTED)
public void transferMoney() {
// 业务逻辑
}
五、事务的生命周期
- 开始事务:通过
TransactionManager
开始事务。 - 执行业务逻辑:在事务范围内执行数据库操作。
- 提交事务:业务成功 →
transactionManager.commit()
。 - 回滚事务:业务失败 →
transactionManager.rollback()
。
关键接口
PlatformTransactionManager
:事务管理器核心接口。TransactionDefinition
:定义事务属性(传播行为、隔离级别、超时时间等)。TransactionStatus
:事务状态对象,用于控制事务流程。
六、异常处理与事务回滚
1. 默认回滚规则
- 未捕获异常:默认回滚事务(如
RuntimeException
及其子类)。 - 已捕获异常:不回滚事务(如
IOException
)。
2. 自定义回滚规则
@Transactional(rollbackFor = {CustomException.class, IOException.class})
public void createUser(User user) {
// 业务逻辑
}
3. 手动触发回滚
try {
// 业务逻辑
} catch (Exception e) {
transactionManager.rollback(status);
throw e;
}
七、数据库事务 vs Spring 事务
对比维度 | 数据库事务 | Spring 事务 |
---|---|---|
管理方式 | 嵌入式在数据库连接中 | 与数据库解耦,通过 AOP 实现 |
事务边界 | 显式通过 BEGIN /COMMIT /ROLLBACK |
通过注解或编程式 API 定义 |
隔离级别 | 数据库特定配置 | 统一配置,兼容多种数据库 |
扩展性 | 有限 | 支持声明式和编程式事务 |
- 查询MySQL事务隔离级别:
select @@global.tx_isolation,@@tx_isolation;
// 全局事务隔离级别 // 当前连接的事务隔离级别
八、实战场景与最佳实践
1. 电商订单流程
@Service
public class OrderService {
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void createOrder(Order order) {
// 1. 扣减库存(需独立事务,避免与其他订单竞争)
inventoryService.deduct(order.getSkuId());
// 2. 生成订单(主事务)
orderDAO.save(order);
// 3. 发送物流事件(异步处理,不影响主事务)
kafkaTemplate.send("logistics_topic", order);
}
}
2. 高并发场景优化
- 缩短事务边界:将大事务拆分为多个小事务。
- 使用乐观锁:通过版本号或时间戳解决并发冲突。
- 降低隔离级别:从
SERIALIZABLE
改为READ_COMMITTED
提升性能。
九、常见问题与解决方案
1. 事务不回滚
- 原因:捕获了异常但未手动回滚。
- 解决:在
rollbackFor
中指定需要回滚的异常类型。
2. 大事务导致性能瓶颈
- 原因:事务长时间占用数据库资源。
- 解决:分库分表、使用缓存、异步处理非关键操作。
3. 死锁问题
- 原因:高并发下多个事务竞争同一资源。
- 解决:设置合理的超时时间、使用
REPEATABLE_READ
隔离级别。
十、总结
Spring 事务管理通过声明式注解和编程式 API,简化了数据库事务的复杂性,核心在于:
- 合理划分事务边界:通过
@Transactional
控制事务范围。 - 配置传播行为和隔离级别:根据业务需求平衡一致性和性能。
- 结合异常处理:确保事务在异常时正确回滚。
- 异步化非关键操作:提升主事务性能。