<前文回顾>
<今日更新>
一、开篇整活儿
今儿个咱唠唠 Spring Boot 里头的事务管理。这玩意儿吧,说大不大,说小不小,整好了是锦上添花,整不好就是火上浇油。你要是刚入门,那可得悠着点儿,别一上来就整得自己“翻车”了。
二、事务管理是啥玩意儿?
事务管理是数据库操作里头的一个核心概念,用来保证一组操作要么全部成功,要么全部失败。Spring Boot 里头默认就集成了事务管理,用起来贼方便。
1. 事务的四大特性
事务有四大特性:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。
- 原子性:事务里头的操作要么全部成功,要么全部失败。
- 一致性:事务执行前后,数据库的状态必须保持一致。
- 隔离性:多个事务并发执行时,一个事务的操作不会影响其他事务。
- 持久性:事务提交后,对数据库的修改是永久性的。
2. 事务的传播行为
Spring Boot 里头,事务有七种传播行为:REQUIRED、REQUIRES_NEW、SUPPORTS、NOT_SUPPORTED、MANDATORY、NEVER、NESTED。
- REQUIRED:如果当前没有事务,就新建一个事务;如果当前有事务,就加入这个事务。
- REQUIRES_NEW:新建一个事务,如果当前有事务,就把当前事务挂起。
- SUPPORTS:如果当前有事务,就加入这个事务;如果当前没有事务,就以非事务方式执行。
- NOT_SUPPORTED:以非事务方式执行,如果当前有事务,就把当前事务挂起。
- MANDATORY:如果当前有事务,就加入这个事务;如果当前没有事务,就抛出异常。
- NEVER:以非事务方式执行,如果当前有事务,就抛出异常。
- NESTED:如果当前有事务,就在当前事务里头嵌套一个子事务;如果当前没有事务,就新建一个事务。
三、声明式事务的使用
Spring Boot 里头的声明式事务是通过注解来实现的,用起来贼方便。
1. 启用事务管理
首先,你得在 Spring Boot 应用里头启用事务管理,用 @EnableTransactionManagement 注解标记。
Java Code |
@SpringBootApplication @EnableTransactionManagement public class MyApplication { public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); } } |
这段代码里头,@EnableTransactionManagement 注解启用了事务管理。
2. 配置事务管理器
然后,你得配置事务管理器,用 @Bean 注解标记。
Java Code |
@Configuration public class TransactionConfig { @Bean public PlatformTransactionManager transactionManager(DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } } |
这段代码里头,transactionManager 方法配置了一个 DataSourceTransactionManager,用来管理事务。
3. 使用 @Transactional 注解
最后,你可以在 Service 里头用 @Transactional 注解标记方法,开启事务。
Java Code |
@Service public class MyService { @Autowired private MyRepository myRepository; @Transactional public void doSomething() { myRepository.doSomething(); } } |
这段代码里头,doSomething 方法用 @Transactional 注解标记了,开启了事务。
四、声明式事务的坑点
1. @Transactional 注解的位置不对
Spring Boot 里头,@Transactional 注解的位置不对,那事务就不起作用了。你要是把注解放在接口上,那可得好好检查检查。
Java Code |
public interface MyService { @Transactional // 放在接口上 void doSomething(); } |
这段代码里头,@Transactional 注解放在接口上,Spring 不会代理这个方法。
2. 事务的传播行为不对
Spring Boot 里头,事务的传播行为不对,那结果就不对了。你要是用错了传播行为,那可得好好调整调整。
Java Code |
@Service public class MyService { @Autowired private MyRepository myRepository; @Transactional(propagation = Propagation.REQUIRES_NEW) public void doSomething() { myRepository.doSomething(); } } |
这段代码里头,doSomething 方法用 REQUIRES_NEW 传播行为,会新建一个事务。
3. 事务的隔离级别不对
Spring Boot 里头,事务的隔离级别不对,那结果就不对了。你要是用错了隔离级别,那可得好好调整调整。
Java Code |
@Service public class MyService { @Autowired private MyRepository myRepository; @Transactional(isolation = Isolation.READ_COMMITTED) public void doSomething() { myRepository.doSomething(); } } |
这段代码里头,doSomething 方法用 READ_COMMITTED 隔离级别,会避免脏读。
五、多说几句
- 对于大多数基本的 Spring Boot 应用程序,事务管理已经通过自动装配机制得到了处理,因此你不需要显式地使用 @EnableTransactionManagement 注解或配置事务管理器。
- 如果你有特殊的事务管理需求,比如自定义事务管理器的配置或额外的控制,那么你可以考虑使用上述步骤1和2。
专有名词解释
- 事务:数据库操作里头的一个核心概念,用来保证一组操作要么全部成功,要么全部失败。
- 原子性:事务里头的操作要么全部成功,要么全部失败。
- 一致性:事务执行前后,数据库的状态必须保持一致。
- 隔离性:多个事务并发执行时,一个事务的操作不会影响其他事务。
- 持久性:事务提交后,对数据库的修改是永久性的。
- 传播行为:Spring Boot 里头的一个概念,用来控制事务的传播方式。
- REQUIRED:Spring Boot 里头的一种传播行为,如果当前没有事务,就新建一个事务;如果当前有事务,就加入这个事务。
- REQUIRES_NEW:Spring Boot 里头的一种传播行为,新建一个事务,如果当前有事务,就把当前事务挂起。
- SUPPORTS:Spring Boot 里头的一种传播行为,如果当前有事务,就加入这个事务;如果当前没有事务,就以非事务方式执行。
- NOT_SUPPORTED:Spring Boot 里头的一种传播行为,以非事务方式执行,如果当前有事务,就把当前事务挂起。
- MANDATORY:Spring Boot 里头的一种传播行为,如果当前有事务,就加入这个事务;如果当前没有事务,就抛出异常。
- NEVER:Spring Boot 里头的一种传播行为,以非事务方式执行,如果当前有事务,就抛出异常。
- NESTED:Spring Boot 里头的一种传播行为,如果当前有事务,就在当前事务里头嵌套一个子事务;如果当前没有事务,就新建一个事务。
- @EnableTransactionManagement:Spring Boot 里头的一个注解,用来启用事务管理。
- PlatformTransactionManager:Spring Boot 里头的一个接口,用来管理事务。
- DataSourceTransactionManager:Spring Boot 里头的一个类,用来管理基于数据源的事务。
- @Transactional:Spring Boot 里头的一个注解,用来开启事务。