Spring 事务管理核心
Spring 事务管理是确保数据库操作符合 ACID(原子性、一致性、隔离性和持久性)特性的核心机制。虽然支持编程式管理,但实际开发中更推荐声明式事务。通过 @Transactional 注解,开发者无需手动编写 begin、commit 或 rollback 代码,Spring 框架会自动处理事务的生命周期。
@Transactional 注解详解
该注解可作用于类或方法级别。作为类注解时,默认仅对类中所有 public 方法生效;作为方法注解时,同样遵循此规则。若将非 public 方法标记为事务,通常不会生效。
@RequestMapping("/test")
@RestController
@Slf4j
public class TestController {
private final UserService userService;
@Autowired
public TestController(UserService userService) {
this.userService = userService;
}
@Transactional
@RequestMapping("/test1")
public String test1(String userName, String password) {
UserInfo userInfo = new UserInfo();
userInfo.setUserName(userName);
userInfo.setPassword(password);
Integer result = userService.register(userInfo);
if (result == 1) {
log.info("test1 注册成功,userName:{},password:{}", userName, password);
}
return "注册成功";
}
}
2.1 rollbackFor:回滚策略
默认情况下,Spring 仅在抛出 非受查异常(RuntimeException) 或 错误(Error) 时触发回滚。如果业务逻辑抛出了受查异常(如 IOException),事务默认会提交。
指定回滚类型
若需捕获受查异常并回滚,必须显式配置 rollbackFor 参数。
@Transactional(rollbackFor = Exception.class)
@RequestMapping("/test4")
public String test4(String userName, String password) throws IOException {
UserInfo userInfo = new UserInfo();
userInfo.setUserName(userName);
userInfo.setPassword(password);
Integer result = userService.register(userInfo);
if (result == 1) {
log.info("test4 注册成功,userName:{},password:{}", userName, password);
throw new IOException(); // 受查异常
}
return "注册成功";
}
此时即使抛出 IOException,事务也会回滚。反之,若未配置且抛出 RuntimeException,则正常回滚;若抛出受查异常,则提交。
2.2 isolation:隔离级别
用于指定事务的隔离级别,可选值包括:
- Isolation.DEFAULT: 使用底层数据库默认的隔离级别。
- Isolation.READ_UNCOMMITTED: 读未提交。
- Isolation.READ_COMMITTED: 读已提交。
- Isolation.REPEATABLE_READ: 可重复读。
- Isolation.SERIALIZABLE: 串行化。
不同隔离级别的具体效果涉及脏读、不可重复读和幻读等概念,具体取决于数据库实现。
2.3 propagation:传播行为
当当前事务方法被另一个事务方法调用时,事务应如何传播?Spring 提供了 7 种传播行为,基于 Propagation 枚举类实现。
Propagation.REQUIRED
默认行为。如果当前存在事务,则加入该事务;如果不存在事务,则新建一个事务。绝大多数场景下使用此项即可。
Propagation.SUPPORTS
如果当前存在事务,则加入该事务;如果不存在事务,则以非事务方式执行。
Propagation.MANDATORY
强制要求当前存在事务并加入,否则抛出异常。适用于必须在事务上下文中运行的方法。
Propagation.REQUIRES_NEW
无论当前是否存在事务,都新建一个事务。新事务与当前事务独立,互不干扰。常用于记录日志或发送通知等需要独立提交的操作。
Propagation.NOT_SUPPORTED
以非事务方式执行操作,如果当前存在事务,则挂起该事务。
Propagation.NEVER
强制要求当前不能存在事务,否则抛出异常。
Propagation.NESTED
如果当前存在事务,则在嵌套事务中执行;如果不存在事务,则行为与 Propagation.REQUIRED 相同。嵌套事务的回滚不影响外部事务,但外部事务回滚会导致嵌套事务回滚。这适用于需要部分回滚的场景,类似于数据库中的 Savepoint。


