Spring Boot 提供了强大的事务管理功能,基于 Spring 的 @Transactional
注解。本文将详细介绍事务的默认配置、事务失效的常见场景、以及事务的几种集中配置方式,并给出相应的代码片段。
一、事务的默认配置
在 Spring Boot 中,默认情况下,事务管理器会自动配置一个 DataSourceTransactionManager
,前提是项目中已经配置了一个数据源(DataSource
)。以下是一些默认行为:
-
传播行为 :
1. 默认传播行为是Propagation.REQUIRED
,即如果当前存在事务,则加入该事务;否则创建一个新的事务。 -
隔离级别 :
- 默认隔离级别是
Isolation.DEFAULT
,即使用底层数据库的默认隔离级别。
- 默认隔离级别是
-
回滚规则 :
- 默认情况下,只有未捕获的
RuntimeException
和Error
会触发事务回滚。 - 检查型异常(Checked Exception)不会触发回滚。
- 默认情况下,只有未捕获的
-
只读属性 :
- 默认情况下,事务不是只读的。
-
超时时间 :
- 默认没有设置超时时间。
二、事务失效的常见场景
尽管 @Transactional
注解非常方便,但在某些情况下,事务可能不会按预期工作。以下是常见的事务失效场景:
1. 方法为 private
或 final
@Service
public class UserService {@Transactionalprivate void updateUser() {// 这里的事务不会生效}
}
2. 同一个类中的方法调用
如果在一个类中,一个非事务方法调用了一个带有 @Transactional
注解的方法,事务也不会生效。因为代理对象不会拦截内部方法调用。
@Service
public class UserService {public void outerMethod() {innerMethod(); // 这里事务不会生效}@Transactionalpublic void innerMethod() {// 事务逻辑}
}
3. 异常被捕获
@Service
public class UserService {@Transactionalpublic void updateUser() {try {// 业务逻辑throw new RuntimeException("Error");} catch (Exception e) {// 异常被捕获,事务不会回滚}}
}
4. 事务方法抛出检查型异常
默认情况下,只有未捕获的 RuntimeException
和 Error
会触发回滚。如果事务方法抛出的是检查型异常(Checked Exception),事务不会回滚
@Service
public class UserService {@Transactionalpublic void updateUser() throws IOException {throw new IOException("Checked Exception"); // 不会触发回滚}
}
三、事务的集中配置及使用场景
Spring Boot 提供了多种事务配置方式,可以根据不同的需求进行选择。
1. 基于注解的事务配置
这是最常见的事务配置方式,使用 @Transactional
注解即可。
使用场景:
简单的事务管理,适用于大多数业务场景。
@Service
public class UserService {@Autowiredprivate UserRepository userRepository;@Transactionalpublic void createUser(User user) {userRepository.save(user);if (user.getName().equals("error")) {throw new RuntimeException("Simulated error");}}
}
2. 基于 XML 配置的事务管理
虽然 Spring Boot 推荐使用注解,但仍然可以通过 XML 配置事务管理。
使用场景
适用于遗留系统或需要更细粒度控制的场景。
<tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><tx:method name="create*" propagation="REQUIRED"/><tx:method name="update*" propagation="REQUIRED"/><tx:method name="delete*" propagation="REQUIRED"/><tx:method name="*" read-only="true"/></tx:attributes>
</tx:advice><aop:config><aop:pointcut id="serviceOperation" expression="execution(* com.example.service.*.*(..))"/><aop:advisor advice-ref="txAdvice" pointcut-ref="serviceOperation"/>
</aop:config>
3. 编程式事务管理
通过 TransactionTemplate
手动控制事务。
使用场景:
@Service
public class UserService {@Autowiredprivate UserRepository userRepository;@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.READ_COMMITTED, timeout = 10)public void createUser(User user) {userRepository.save(user);}@Transactional(readOnly = true)public List<User> getAllUsers() {return userRepository.findAll();}
}
四、总结
Spring Boot 提供了灵活且强大的事务管理机制,默认配置可以满足大部分场景的需求。但在实际开发中,需要注意事务失效的常见场景,并根据业务需求选择合适的事务配置方式。
- 默认配置 :适用于大多数简单场景。
- 失效场景 :注意方法访问修饰符、异常处理、同一类方法调用等问题。
- 集中配置 :可以根据需求选择注解、XML、编程式或自定义事务属性的方式。