网站备案了以后,邢台seo技术,做建网站的工作一年赚几百万,政务服务平台一、事务的隔离级别
在Springboot应用中#xff0c;如果我们想实现方法一旦执行有异常产生#xff0c;就触发事务回滚#xff0c;可以在方法上面添加Transactional注解。如果应用采用mysql数据库#xff0c;虽然mysql本身也有事务隔离机制#xff0c;但在Sping数据库的应…一、事务的隔离级别
在Springboot应用中如果我们想实现方法一旦执行有异常产生就触发事务回滚可以在方法上面添加Transactional注解。如果应用采用mysql数据库虽然mysql本身也有事务隔离机制但在Sping数据库的应用中会以Spring事务为准。mysql定义的事务隔离级别为可重复读在使用 Spring Boot 和 MySQL 的组合时如果你不特别指定隔离级别那么实际使用的将是 MySQL 的默认值 REPEATABLE READ。如果在一些特定场景中不想使用可重复读可通过Transactional注解的isolation属性来指定。isolation支持的选项有
ISOLATION_DEFAULT使用后端数据库默认的隔离级别。ISOLATION_READ_UNCOMMITTED最低的隔离级别允许读取尚未提交的数据变更可能会导致脏读、不可重复读或幻读。ISOLATION_READ_COMMITTED允许读取已经提交的数据可以防止脏读但可能会出现不可重复读或幻读。ISOLATION_REPEATABLE_READ对同一字段的多次读取结果是一致的除非数据是被当前事务本身所修改可以防止脏读和不可重复读但幻读仍可能发生。ISOLATION_SERIALIZABLE最高的隔离级别完全服从 ACID 的隔离级别所有的事务依次逐个执行可以防止脏读、不可重复读以及幻读。
使用示例 Transactional(isolation Isolation.READ_COMMITTED) public void performTransaction() { // 业务逻辑代码 } 二、事务的传播行为
事务的传播行为是指当一个事务方法被另一个事务方法调用时两者之间的事务应该如何关联。通过配置不同的传播行为可以控制是否应该创建新的事务、加入现有事务或者以非事务方式执行等。
Spring 提供了七种标准的事务传播行为它们可以通过 Transactional 注解的 propagation 属性来指定。以下是这些传播行为的详细说明 PROPAGATION_REQUIRED (默认) 如果当前存在事务则加入该事务如果不存在则创建一个新的事务。 这是最常用的传播行为适用于大多数场景。PROPAGATION_SUPPORTS 如果当前存在事务则加入该事务如果不存在则以非事务方式执行。 适合那些对事务性没有特别要求的操作如查询操作。PROPAGATION_MANDATORY 如果当前存在事务则加入该事务如果不存在则抛出异常IllegalTransactionStateException。 用于强制要求在已有事务中执行的方法。PROPAGATION_REQUIRES_NEW 创建一个新的事务如果当前存在事务则将当前事务挂起。 适用于需要独立于外部事务执行的业务逻辑确保内部操作不会影响外部事务的结果。PROPAGATION_NOT_SUPPORTED 以非事务方式执行操作如果当前存在事务则将当前事务挂起。 适合那些明确不需要事务的操作如读取系统配置或发送邮件等。PROPAGATION_NEVER 以非事务方式执行如果当前存在事务则抛出异常IllegalTransactionStateException。 用于严格禁止在事务环境中执行的方法。PROPAGATION_NESTED 如果当前存在事务则在嵌套事务内执行如果不存在则创建一个新的事务。 嵌套事务是外部事务的一部分但可以独立于外部事务进行提交或回滚。这种传播行为依赖于底层数据库和驱动的支持例如 MySQL 的 InnoDB 引擎支持保存点SAVEPOINT从而实现嵌套事务。 注意事项 性能考虑选择合适的传播行为对于性能优化非常重要。例如PROPAGATION_REQUIRES_NEW 和 PROPAGATION_NOT_SUPPORTED 都会涉及到事务的挂起和恢复这可能会带来额外的开销。 事务边界正确理解事务的边界以及传播行为的影响有助于避免潜在的问题如死锁、数据不一致等。 嵌套事务支持不是所有的数据库都支持嵌套事务。使用 PROPAGATION_NESTED 时请确保你的数据库和驱动程序支持这一特性。 根据应用的具体需求选择适当的传播行为可以帮助你更好地管理事务确保数据的一致性和完整性。
三、Spring事务中存在的坑
在同一个类里面编写两个方法内部调用的时候会导致事务设置失效。原因是没有用到 代理对象的缘故。具体来说
Spring 使用 AOP 来实现事务管理它会为每个带有 Transactional 注解的方法创建一个代理对象。当你通过 Spring 容器获取这个类的实例并调用其方法时实际上是调用了代理对象的方法而不是原始类的方法。代理对象负责在方法调用前后插入事务管理逻辑。
然而当你在一个类的非静态方法中直接调用另一个 Transactional 方法时调用并没有经过代理对象而是直接调用了原始类的方法。因此事务管理逻辑不会被应用导致事务设置失效。
方法1 1、导入spring-boot-starter-aop依赖 2、启动类添加注解EnableAspectJAutoProxy(exposeProxytrue) 3、事务使用的地方使用AopContext.currentProxy() 调用方法。
使用示例
import org.springframework.aop.framework.AopContext;Service
public class MyService {Transactionalpublic void transactionalMethod() {// 事务逻辑}public void performOperation() {// 业务逻辑((MyService) AopContext.currentProxy()).transactionalMethod();}
}
不过这种方式使得代码更加复杂且不直观因此尽量避免使用除非绝对必要。
最推荐的做法是将事务方法移到不同的类中。这样可以确保每次调用事务方法时都通过代理对象进行从而保证事务管理生效。具体可参考方法2
方法2
Service
public class MyService {Autowiredprivate AnotherService anotherService;public void performOperation() {// 业务逻辑anotherService.transactionalMethod();}
}Service
public class AnotherService {Transactionalpublic void transactionalMethod() {// 事务逻辑}
}
拓展Transactional支持的配置属性大盘点
除了上面提到的propagation和isolationTransactional 注解里边还支持配置以下属性
1. value 或 transactionManager
作用指定要使用的事务管理器的名称。如果你的应用程序中有多个事务管理器例如针对不同的数据源你可以使用这个属性来明确指定哪一个事务管理器应该管理当前方法的事务。默认值transactionManager这是 Spring 默认的事务管理器 Bean 名称。 Transactional(myTransactionManager) public void myTransactionalMethod() { // 业务逻辑 } 2. readOnly
作用指定事务是否为只读事务。只读事务通常用于查询操作可以提高性能例如禁用脏页写入等。取值 false默认事务不是只读的允许进行插入、更新和删除操作。true事务是只读的仅允许查询操作。 Transactional(readOnly true) public ListEntity findAllEntities() { // 查询操作 } 3. timeout 作用定义事务的超时时间单位为秒。如果事务在指定时间内未能完成Spring 会自动回滚事务。 默认值-1表示使用后端数据库或事务管理器的默认超时设置。 Transactional(timeout 30) public void longRunningOperation() { // 长时间运行的业务逻辑 } 4. rollbackFor 作用指定哪些异常应该触发事务回滚。默认情况下只有未检查异常如 RuntimeException 及其子类会触发回滚。你可以通过这个属性指定其他异常类型也应触发回滚。 取值一个或多个异常类可以用逗号分隔。 Transactional(rollbackFor {CustomCheckedException.class, AnotherException.class}) public void methodThatMayThrowExceptions() { // 业务逻辑 } 5. noRollbackFor 作用指定哪些异常不应该触发事务回滚。默认情况下所有未检查异常都会触发回滚但你可以通过这个属性指定某些异常不应触发回滚。 取值一个或多个异常类可以用逗号分隔。 Transactional(noRollbackFor CustomCheckedException.class) public void methodThatMayThrowCustomException() { // 业务逻辑 } 6. validation 作用指定是否在事务开始之前验证事务属性。如果设置为 trueSpring 会在事务开始前检查事务属性是否符合要求如果不符则抛出异常。 默认值false即不进行验证。 Transactional(validation true) public void validateTransactionalAttributes() { // 业务逻辑 }