在 Spring 中,事务管理主要有两种方式:编程式事务 和声明式事务。它们的核心目标都是保证数据操作的原子性、一致性、隔离性和持久性(ACID),但实现方式和适用场景有显著区别。
编程式事务
编程式事务 是通过手动编写代码来控制事务的开启、提交、回滚等操作,开发者需要显式地管理事务的生命周期,核心类是 TransactionTemplate,它依赖 PlatformTransactionManager(事务管理器)来完成实际的事务操作。
java
@Service
public class UserService {
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private PlatformTransactionManager transactionManager;
public void transferMoney(Long fromId, Long toId, int amount) {
// 1. 定义事务属性(传播行为、隔离级别等)
TransactionDefinition definition = new DefaultTransactionDefinition() {{
setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
setTimeout(30); // 超时时间 30 秒
}};
// 2. 开启事务
TransactionStatus status = transactionManager.getTransaction(definition);
try {
// 执行数据库操作(扣钱)
jdbcTemplate.update("UPDATE user SET balance = balance - ? WHERE id = ?", amount, fromId);
// 执行数据库操作(加钱)
jdbcTemplate.update("UPDATE user SET balance = balance + ? WHERE id = ?", amount, toId);
// 3. 无异常则提交事务
transactionManager.commit(status);
} catch (Exception e) {
// 4. 有异常则回滚事务
transactionManager.rollback(status);
throw new RuntimeException("转账失败", e);
}
}
}
声明式事务
声明式事务 是基于 AOP(面向切面编程),通过 @Transactional 注解或 XML 配置定义事务属性,在运行时动态生成代理对象,拦截目标方法并管理事务。需在 Spring 配置类中定义事务管理器(如 @EnableTransactionManagement 开启注解驱动,并注册 DataSourceTransactionManager)。
自调用失效 :同一类中,一个无事务方法调用另一个有事务的方法时,事务不会生效(因 Spring 事务基于 AOP 代理,自调用不会经过代理对象)解决:注入自身 Bean 或通过 AopContext.currentProxy() 获取代理对象调用。
@Transactional 可标注在 类 或 方法 上:
- 标注在类上:表示该类中所有公共方法(
public)都默认应用该事务配置。 - 标注在方法上:表示该方法单独使用事务配置(方法级配置会覆盖类级配置)。
事务管理器(多数据源场景下需指定):value/transactionManager
事务传播行为(propagation):propagation = Propagation.REQUIRED(默认)如果当前已经存在事务 (即调用该方法的外层方法已有事务),则加入当前事务 ,方法与外层事务共用一个事务(同成功、同回滚)。如果当前没有事务 (外层方法无事务),则创建一个新的事务,方法在新事务中执行。
事务隔离级别(isolation):DEFAULT:使用数据库默认隔离级别(如 MySQL 默认为 REPEATABLE_READ)。
只读事务readOnly:默认false
事务超时时间time:(秒):默认-1无超时时间,超时后自动回滚。
回滚规则:默认情况下,事务仅在抛出 未捕获的 RuntimeException 或 Error 时回滚; checked 异常(如 IOException)不会触发回滚,可过 rollbackFor 或 noRollbackFor 自定义
PlatformTransactionManager
两种方式的底层都依赖Spring 框架的 PlatformTransactionManager 接口实现事务的具体操作(如提交、回滚),只是编程式需要手动触发,而声明式由 Spring 自动触发。
PlatformTransactionManager 负责管理事务的生命周期,包括:
- 开启事务(
getTransaction(...)) - 提交事务(
commit(...)) - 回滚事务(
rollback(...))
它是一个**抽象接口,**具体的事务管理逻辑由其实现类根据不同的资源类型(如 JDBC、JPA、Hibernate 等)实现。
| 实现类 | 适用场景 | 依赖资源 |
|---|---|---|
DataSourceTransactionManager |
管理 JDBC 事务(最常用) | javax.sql.DataSource |
JpaTransactionManager |
管理 JPA 事务 | JPA EntityManagerFactory |
HibernateTransactionManager |
管理 Hibernate 事务(旧版本 Hibernate) | Hibernate SessionFactory |
JtaTransactionManager |
管理分布式事务(跨多个资源,如多数据库) | JTA 环境(如 Java EE 容器) |
RabbitTransactionManager |
管理 RabbitMQ 消息队列事务 | RabbitMQ ConnectionFactory |