Spring事务失效常见的五种方式及其解决方案

本文总结了Spring 声明式事务的源码实现、五种常见的事务失效情况,并提供了相应的解决方案 。

Spring事务失效常见的五种方式及其解决方案

文章插图
一、前言在Web 开发中,Spring 框架已经成为了众多开发者的首选 。Spring 的声明式事务管理是其中最重要的特性之一,它可以帮助我们简化业务逻辑的复杂度,并且确保在出现异常情况时数据的一致性 。
事务失效情况很常见,但我们只要注意,就可以避免事情发生!在本文中,我将详细地介绍 Spring 声明式事务的源码实现和事务失效常见的五种情况,并给出有效的解决方案 。
其实我们常说的事务失效是声明式事务(@Transactional)的失效,本文也是从声明式事务来进行演示的!
通过本文的学习,你将掌握如何正确地使用 Spring 的事务管理,减少生产事故 。
「一定要保持数据一致性」 。
二、@Transactional注解参数解读我们拿出几个经常使用的参数来简单介绍一下:
  • propagation:指定事务的传播行为 。其取值包括 REQUIRED、SUPPORTS、MANDATORY、REQUIRES_NEW、NOT_SUPPORTED、NEVER 和 NESTED 等 。默认为 REQUIRED 。其中,REQUIRED 表示如果当前已经存在一个事务,则加入该事务,否则新建一个事务;而 REQUIRES_NEW 表示新建一个独立的事务,如果当前已经存在事务,则挂起当前事务 。后面就不一一说了,大家可以自行百度哈!
  • isolation:指定事务的隔离级别 。其取值包括 DEFAULT、READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ 和 SERIALIZABLE 等 。默认为 DEFAULT 。其中,DEFAULT 表示采用数据库的默认隔离级别.
  • timeout:指定事务的超时时间,单位为秒 。默认为 -1,表示不设置超时时间 。如果在规定时间内事务还未完成,则抛出 TransactionTimedOutException 异常 。
  • readOnly:指定事务是否只读,即是否允许修改数据 。默认为 false,表示可以进行数据修改操作 。如果将其设置为 true,则表示该事务仅能进行数据查询操作,不能进行数据修改操作,这样可以提高并发性能 。
  • rollbackFor:指定哪些异常需要回滚事务 。其取值为一个 Class 数组,其中每个元素表示一个异常类型 。默认为空,表示只有抛出 RuntimeException 或 Error 类型的异常时才回滚事务 。
  • noRollbackFor:指定哪些异常不需要回滚事务 。其取值为一个 Class 数组,其中每个元素表示一个异常类型 。默认为空,表示抛出任何异常都回滚事务 。
三、声明式事务源码实现声明式事务实现类为:TransactionInterceptor ,下面我们来一起看看这个类!
【Spring事务失效常见的五种方式及其解决方案】源码版本为Springboot2.7.1 。
public class TransactionInterceptor extends TransactionAspectSupportimplements MethodInterceptor, Serializable{}TransactionInterceptor UML图:
Spring事务失效常见的五种方式及其解决方案

文章插图
声明式事务主要是通过AOP实现,主要包括以下几个节点:
  1. 启动时扫描@Transactional注解:在启动时,Spring Boot会扫描所有使用了@Transactional注解的方法,并将其封装成TransactionAnnotationParser对象 。
  2. AOP 来实现事务管理的核心类依然是 TransactionInterceptor 。TransactionInterceptor 是一个拦截器,用于拦截使用了 @Transactional 注解的方法
  3. 将TransactionInterceptor织入到目标方法中:在AOP编程中,使用AspectJ编写切面类,通过@Around注解将TransactionInterceptor织入到目标方法中 。
  4. 在目标方法执行前创建事务:在目标方法执行前,TransactionInterceptor会调用PlatformTransactionManager创建一个新的事务,并将其纳入到当前线程的事务上下文中 。
  5. 执行目标方法:在目标方法执行时,如果发生异常,则将事务状态标记为ROLLBACK_ONLY;否则,将事务状态标记为COMMIT 。
  6. 提交或回滚事务:在目标方法执行完成后,TransactionInterceptor会根据事务状态(COMMIT或ROLLBACK_ONLY)来决定是否提交或回滚事务 。
源码:
@Override@Nullablepublic Object invoke(MethodInvocation invocation) throws Throwable { // Work out the target class: may be {@code null}. // The TransactionAttributeSource should be passed the target class // as well as the method, which may be from an interface. Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null); // Adapt to TransactionAspectSupport's invokeWithinTransaction... return invokeWithinTransaction(invocation.getMethod(), targetClass, new CoroutinesInvocationCallback() {@Override@Nullablepublic Object proceedWithInvocation() throws Throwable {return invocation.proceed();}@Overridepublic Object getTarget() {return invocation.getThis();}@Overridepublic Object[] getArguments() {return invocation.getArguments();} });}


推荐阅读