事务
@Transactional注解
- 方法可见性:
@Transactional注解应用于公有方法上。如果注解在非公有方法上,事务可能不会生效 - 异常处理:默认情况下,只有运行时异常(非受检异常)会导致事务回滚。如果需要受检异常(例如
IOException)也触发回滚,需要在注解中明确指定 - 事务传播行为:默认传播行为是
REQUIRED,如果当前没有事务,则创建一个新事务,如果有,则加入当前事务。根据业务需求,可能需要设置不同的传播行为 - 事务配置:确保事务管理器正确配置,并且注解驱动的事务管理已经开启(通常通过
@EnableTransactionManagement注解) - 自调用问题:自调用(即一个类中的非事务方法调用本类中的事务方法)可能导致事务注解失效
事务传播级别Propagation
| 传播级别 | 应用场景 | 调用时存在事务 | 调用时无事务 | 是否新建事务 | 注意事项 |
|---|---|---|---|---|---|
| REQUIRED | 电商下单(订单创建+库存扣减需原子性),转账操作(A账户扣款+B账户入账) | 加入当前事务 | 创建新事务 | 按需创建 | 默认级别,但需避免事务方法执行时间过长(如循环调用) |
| SUPPORTS | 商品列表查询(可适应事务/非事务环境),用户信息读取(低一致性要求) | 加入当前事务 | 非事务执行 | 否 | 非事务执行时可能读到脏数据(需结合业务容忍度) |
| MANDATORY | 资金结算(必须依赖上游事务) ,权限校验(需在事务中记录操作日志) | 加入当前事务 | 抛出异常 | 否 | 适用于底层工具类方法(如审计日志),强制调用方开启事务 |
| REQUIRES_NEW | 异步任务触发(如短信发送,需独立提交) ,操作日志记录(避免主事务回滚影响日志) | 挂起当前事务,创建新事务 | 创建新事务 | 是(完全独立) | 新事务独立提交,但可能导致锁竞争(如并发日志写入需加分布式锁) |
| NOT_SUPPORTED | 发送站内通知(非核心操作) ,写入本地缓存(避免事务锁阻塞) | 挂起当前事务,非事务执行 | 非事务执行 | 否 | 强制脱离事务,但需注意非事务执行的线程安全问题(如缓存更新) |
| NEVER | 加载静态配置(如读取本地JSON文件) ,健康检查(仅查询服务状态) | 抛出异常 | 非事务执行 | 否 | 严格限制事务上下文,适用于工具类初始化方法 |
| NESTED | 批量导入数据(单条失败跳过,继续处理) ,复杂计算中间结果保存(可回滚部分步骤) | 嵌套事务(基于保存点) | 创建新事务(行为同REQUIRED) | 按需创建(逻辑嵌套) | 仅Oracle等支持保存点的数据库有效,MySQL需改用REQUIRES_NEW+补偿机制 |
- 优先默认(REQUIRED):适用于80%的增删改操作
- 读操作优化:对查询方法使用
SUPPORTS或NOT_SUPPORTED,结合readOnly=true提升性能 - 事务隔离性:
REQUIRES_NEW和NESTED的选择需权衡数据库兼容性和业务需求 - 分布式事务:跨服务调用时(如订单+库存服务),避免依赖本地事务传播级别,改用Seata等方案
自调用场景
@Transactional注解实际上是应用了AOP代理。当外部方法调用带有@Transactional注解的方法时,Spring AOP会在方法执行前启动事务,并在方法执行结束后提交或回滚事务
在自调用场景中ServiceA.java
java
public class ServiceA {
public void methodA() {
// ... do something
methodB(); // 自调用
// ... do something else
}
@Transactional
public void methodB() {
// ... transactional operations
}
}
methodA()直接调用methodB(),它不是通过Spring AOP代理调用的,而是直接在同一个对象实例上调用的Java方法,因此,Spring AOP代理无法截获这个调用,也就无法应用事务管理
注入自身
通过Spring容器注入自身代理,然后通过代理调用事务方法
ServiceA.java
java
public class ServiceA {
@Autowired
private ServiceA self;
public void methodA() {
// ... do something
self.methodB(); // 通过代理调用
// ... do something else
}
@Transactional
public void methodB() {
// ... transactional operations
}
}
self.methodB()是通过Spring AOP代理调用的,因此事务注解会生效
手动管理事务
配置类
注入对应的对象TransactionTemplate,新增配置类TransactionConfig.java
java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.support.TransactionTemplate;
@Configuration
public class TransactionConfig {
@Autowired
private PlatformTransactionManager transactionManager;
@Bean
public TransactionTemplate transactionTemplate() {
TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
// 设置事务传播行为为REQUIRED,表示如果当前存在事务,则加入该事务;如果不存在,则创建一个新的事务
transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
// 设置事务隔离级别为READ_COMMITTED,表示一个事务可能看到另一个事务已提交的数据
transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
// 设置事务超时时间为30秒,如果在30秒内事务没有完成,则自动回滚
transactionTemplate.setTimeout(30);
return transactionTemplate;
}
}常用方法
setPropagationBehavior(int propagationBehavior):设置事务的传播行为,例如TransactionDefinition.PROPAGATION_REQUIREDsetIsolationLevel(int isolationLevel):设置事务的隔离级别,例如TransactionDefinition.ISOLATION_DEFAULTsetTimeout(int timeout):设置事务的超时时间,单位为秒executeWithoutResult(TransactionCallbackWithoutResult action):执行不需要返回结果的事务操作- java
@Service public class MyService { // 自动注入TransactionTemplate @Autowired private TransactionTemplate transactionTemplate; // 服务层方法,使用TransactionTemplate执行事务 public void performOperation() { // 使用注入的transactionTemplate执行事务操作 transactionTemplate.executeWithoutResult(status -> { try { // 执行事务操作,例如保存对象到数据库 repository.save(someObject); } catch (Exception e) { // 出现异常时回滚事务 status.setRollbackOnly(); // 可以选择抛出异常或进行其他错误处理 throw e; } }); } }
execute(TransactionCallback<T> action):执行需要返回结果的事务操作- java
@Service public class MyService { // 自动注入TransactionTemplate @Autowired private TransactionTemplate transactionTemplate; // 服务层方法,使用TransactionTemplate执行事务 public Integer performUpdateOperation() { // 使用注入的transactionTemplate执行事务操作 return transactionTemplate.execute(status -> { try { // 执行事务操作,例如更新数据库中的记录 int updatedCount = repository.update(someObject); // 返回操作结果 return updatedCount; } catch (Exception e) { // 出现异常时回滚事务 status.setRollbackOnly(); // 可以选择抛出异常或进行其他错误处理 throw e; } }); } }
