Spring Boot 事务示例详解
目录
- Spring Boot 事务详解
- 引言
- 声明式事务管理
- 示例
- 编程式事务管理
- 示例
- 事务传播行为
- 1. REQUIRED
- 2. SUPPORTS
- 3. MANDATORY
- 4. REQUIRES_NEW
- 5. NOT_SUPPORTED
- 6. NEVER
- 7. NESTED
- 事务失效情况
- 1. 未捕获异常
- 2. 非受检异常
- 3. 事务传播属性设置不当
- 4. 多数据源的事务管理
- 5. 跨方法调用事务问题
- 6. 事务在非公开方法中失效
- 7. 使用this调用事务方法
- 事务属性
- 1. 隔离级别
- 2. 事务超时
- 3. 只读事务
- 4. 回滚规则
- 常见面试题解析
- 1. 什么是事务传播行为?Spring 提供了哪些事务传播行为?
- 2. 如何配置事务的隔离级别?Spring 提供了哪些隔离级别?
- 3. 什么是只读事务?如何配置?
- 4. 如何配置事务的超时时间?
- 5. 如何指定哪些异常会触发事务回滚?
- 总结
Spring Boot 事务详解
引言
在现代应用程序中,事务管理是确保数据一致性和完整性的重要机制。Spring Boot 提供了强大的事务管理功能,使得开发者可以轻松地定义和管理事务。本文将详细介绍 Spring Boot 中的事务管理,包括事务传播行为、事务属性以及声明式和编程式事务管理。
声明式事务管理
声明式事务管理是通过注解的方式来管理事务,最常用的注解是 @Transactional
。这种javascript方式简单直观,适合大多数场景。
示例
import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service public class UserService { @Transactional public void createUser(User user) { // 数据库操作 } }
编程式事务管理
编程式事务管理是通过编程的方式来手动控制事务,通常使用 PlatformTransactionManager
和 TransactionTemplate
。
示例
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionDefinition; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.DefaultTransactionDefinition; @Service public class UserService { @Autowired private PlatformTransactionManager transactionManager; public void createUser(User user) { DefaultTransactionDefinition def = new DefaultTransactionDefinition(); def.setName("createUserTransaction"); def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); TransactionStatus status = transactionManager.getTransaction(def); try { // 数据库操作 transactionManager.commit(status); } catch (Exception e) { transactionManager.rollback(status); throw e; } } }
事务传播行为
事务传播行为定义了当一个事务方法调用另一个事务方法时,事务如何传播。Spring 提供了多种传播行为,可以通过 @Transactional
注解进行配置。以下是 Spring 支持的传播行为及其使用场景:
1. REQUIRED
定义:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
使用场景:大多数业务操作都使用该传播行为,因为它确保了调用链上的所有操作都在同一个事务中。
示例:
@Transactional(propagation = Propagation.REQUIRED) public void methodA() { 编程 // 业务逻辑 }
事务传播示意图:
+--------+ +--------+ | 方法A | | 方法B | | |---------------> | | | 传播事务 T1 | | +--------+ +--------+
2. SUPPORTS
定义:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务方式执行。
使用场景:适用于可选的事务操作,例如只读查询。
示例:
@Transactional(propagation = Propagation.SUPPORTS) public void methodB() { // 业务逻辑 }
事务传播示意图:
+--------+ +--------+ | 方法A | | 方法B | | |---------------> | | | 传播事务 T1 | | +--------+ +--------+
3. MANDATORY
定义:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
使用场景:用于强制要求在事务环境中执行的方法。
示例:
@Transactional(propagation = Propagation.MANDATORY) public void methodC() { // 业务逻辑 }
事务传播示意图:
+--------+ +--------+ | 方法A | | 方法C | | |---------------> | | | 传播事务 T1 | | +--------+ +--------+
4. REQUIRES_NEW
定义:创建一个新的事务,如果当前存在事务,则将当前事务挂起。
使用场景:适用于必须在一个新事务中执行的操作,例如独立的日志记录。
示例:
@Transactional(propagation = Propagation.REQUIRES_NEW) public void methodD() { // 业务逻辑 }
事务传播示意图:
+--------+ +--------+ | 方法A | | 方法D | | |------------->| | | 挂起事务 T1 | 创建事务 T2 | +--------+ +--------+
5. NOT_SUPPORTED
定义:以非事务方式执行操作,如果当前存在事务,则将当前事务挂起。
使用场景:适用于不需要事务的操作,例如批量数据处理。
示例:
@Transactional(propagation = Propagation.NOT_SUPPORTED) public void methodE() { // 业务逻辑 }
事务传播示意图:
+--------+ +--------+ | 方法A | | 方法E | | |------------->| | | 挂起事务 T1 | 非事务执行 | +--------+ +--------+
6. NEVER
定义:以非事务方式执行,如果当前存在事务,则抛出异常。
使用场景:用于强制要求以非事务方式执行的方法。
示例:
@Transactional(propagation = Propagation.NEVER) public void methodF() { // 业务逻辑 }
事务传播示意图:
+--------+ +--------+ | 方法A | | 方法F | | |------------->| | | | 如果存在事务 T1,抛异常 | +--------+ +--------+
7. NESTED
定义:如果当前存在事务,则在嵌套事务内执行;如果当前没有事务,则行为与 REQUIRED
类似。
使用场景:适用于需要在主事务中执行的子事务,例如复杂的数据库操作。
示例:
@Transactional(propagation = Propagation.NESTED) public void methodG() { // 业务逻辑 }
事务传播示意图:
+--------+ +--------+ | 方法A | | 方法G | | |------------->| | | 事务 T1 | 嵌套事务 T1.1 | +--------+ +--------+
事务失效情况
Spring Boot 通过 Spring 框架的事务管理模块来支持事务操作。事务管理在 Spring Boot 中通常是通过 @Transactional
注解来实现的。以下是一些常见的事务失效情况:
1. 未捕获异常
如果一个事务方法中发生了未捕获的异常,并且异常未被处理或传播到事务边界之外,那么事务会失效,所有的数据库操作会回滚。
2. 非受检异常
默认情况下,Spring 对非受检异常(RuntimeException
或其子类)进行回滚处理,这意味着当事务方法中抛出这些异常时,事务会回滚。
3. 事务传播属性设置不当
如果在多个事务之间存在事务嵌套,且事务传播属性配置不正确,可能导致事务失效。特别是在方法内部调用有 @Transactional
注解的方法时要特别注意。
4. 多数据源的事务管理
如果在使用多数据源时,事务管理没有正确配置或者存在多个 @Transactional
注解时,可能会导致事务失效。
5. 跨方法调用事务问题
如果一个事务方法内部调用另一个方法,而这个被调用的方法没有 @Transactional
注解,这种情况下外层事务可能会失效。
6. 事务在非公开方法中失效
如果 @Transactional
注解标注在私有方法上或者非 public
方法上,事务也会失效。
7. 使用this调用事务方法
Spring 事务是通过代理对象来控制的,只有通过代理对象的方法调用才会应用事务管理的相关规则。当使用 this
直接调用时,是绕过了 Spring 的代理机制,因此不会应用事务设置。
回滚条件
1. 自动回滚事务
抛出未检查异常(RuntimeException
及其子类),例如:NullPointerException
等。
2. 不会自动回滚
默认情况下,检查异常(如 IOException
、SQLException
等)不会触发回滚。可以通过 @Transactional
注解的 rollbackFor
属性配置回滚:
示例:
@Transacthttp://www.devze.comional(rollbackFor = IOException.class) public void methodH() { // 业务逻辑 }
事务属性
除了传播行为,Spring 还提供了一些其他事务属性,可以通过 @Transactional
注解进行配置。
1. 隔离级别
隔离级别定义了一个事务与其他事务隔离的程度。Spring 支持以下几种隔离级别:
- DEFAULT:使用数据库默认的隔离级别。
- READ_UNCOMMITTED:读未提交的变更。
- READ_COMMITTED:读已提交的变更。
- REPEATABLE_READ:可重复读。
- SERIALIZABLE:串行化。
示例:
@Transactional(isolation = Isolation.READ_COMMITTED) public void methodI()www.devze.com { // 业务逻辑 }
2. 事务超时
事务超时定义了事务在回滚之前可以运行的最长时间(以秒为单位)。
示例:
@Transactional(timeout = 30) public void methodJ() { // 业务逻辑 }
3. 只读事务
只读事务用于优化只读操作。设置为只读的事务可以提示数据库引擎进行某些优化。
示例:
@Transactional(readOnly = true) public void methodK() { // 业务逻辑 }
4. 回滚规则
通过 rollbackFor
和 noRollbackFor
属性可以指定哪些异常会触发事务回滚,哪些不会。
示例:
@Transactional(rollbackFor = Exception.class) public void methodL() { // 业务逻辑 }
常见面试题解析
1. 什么是事务传播行为?Spring 提供了哪些事务传播行为?
答:事务传播行为定义了当一个事务方法调用另一个事务方法时,事务如何传播。Spring 提供了以下事务传播行为:REQUIRED、SUPPORTS、MANDATORY、REQUIRES_NEW、NOT_SUP编程客栈PORTED、NEVER、NESTED。
2. 如何配置事务的隔离级别?Spring 提供了哪些隔离级别?
答:可以通过 @Transactional
注解的 isolation
属性配置事务的隔离级别。Spring 提供了以下隔离级别:DEFAULT、READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ、SERIALIZABLE。
3. 什么是只读事务?如何配置?
答:只读事务用于优化只读操作。可以通过 @Transactional
注解的 readOnly
属性配置只读事务。例如:@Transactional(readOnly = true)
。
4. 如何配置事务的超时时间?
答:可以通过 @Transactional
注解的 timeout
属性配置事务的超时时间(以秒为单位)。例如:@Transactional(timeout = 30)
。
5. 如何指定哪些异常会触发事务回滚?
答:可以通过 @Transactional
注解的 rollbackFor
属性指定哪些异常会触发事务回滚。例如:@Transactional(rollbackFor = Exception.class)
。
总结
Spring Boot 提供了强大的事务管理功能,通过 @Transactional
注解可以方便地配置事务的传播行为和属性。理解和合理应用这些配置,可以有效地提高应用程序的数据一致性和完整性。
到此这篇关于Spring Boot 事务示例详解的文章就介绍到这了,更多相关Spring Boot 事务内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!
精彩评论