Spring - TransactionalEventListener 解决事务未提交读取不到数据问题(二)

简介: Spring - TransactionalEventListener 解决事务未提交读取不到数据问题(二)

三、解决问题方案

解决思路是在事务提交后再做其他的处理(如异步发消息处理等),这里还是从Spring执行事务的过程中入手,Spring事务的处理过程不再分析,这里直接看Spring事务增强器TransactionInterceptor的核心处理流程,源码如下:


protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation) throws Throwable {
  // 获取事务属性
  final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
  //加载配置中配置的TransactionManager
  final PlatformTransactionManager tm = determineTransactionManager(txAttr);
  final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
  // 声明式事务的处理
  if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
    TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
    Object retVal = null;
    //......
    retVal = invocation.proceedWithInvocation();
    //......
    commitTransactionAfterReturning(txInfo);
    return retVal;
  } else {
    // 编程式事务的处理......
  }
  //......
}

这里主要看声明式事务的处理,因为编程式事务的处理及提交都是用户在编码中进行控制。在声明式事务处理中,当方法执行完后,会执行 commitTransactionAfterReturning 方法来进行提交事务,该方法在 TransactionAspectSupport 类中,源码如下:


protected void commitTransactionAfterReturning(TransactionInfo txInfo) {
  if (txInfo != null && txInfo.hasTransaction()) {
    txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
  }
}

再看 commit 方法,该方法在 AbstractPlatformTransactionManager 类中,源码如下:

public final void commit(TransactionStatus status) throws TransactionException {
    // 这里省略很多代码,如事务回滚......
    processCommit(defStatus);
}
private void processCommit(DefaultTransactionStatus status) throws TransactionException {
    try {
      boolean beforeCompletionInvoked = false;
      try {
        prepareForCommit(status);
        triggerBeforeCommit(status);
        triggerBeforeCompletion(status);
        beforeCompletionInvoked = true;
        boolean globalRollbackOnly = false;
        if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) {
          globalRollbackOnly = status.isGlobalRollbackOnly();
        }
        if (status.hasSavepoint()) {
          status.releaseHeldSavepoint();
        } else if (status.isNewTransaction()) {
          // 提交事务
          doCommit(status);
        }
        //......
      } catch (......) {
        // 事务异常处理......
      }
      try {
        // 事务提交成功后的处理-----这里是重点
        triggerAfterCommit(status);
      } finally {
        triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED);
      }
    }
    finally {
      cleanupAfterCompletion(status);
    }
}
private void triggerAfterCommit(DefaultTransactionStatus status) {
  if (status.isNewSynchronization()) {
    TransactionSynchronizationUtils.triggerAfterCommit();
  }
}

最终会走到 TransactionSynchronizationUtils.triggerAfterCommit() 方法中


public static void triggerAfterCommit() {
    invokeAfterCommit(TransactionSynchronizationManager.getSynchronizations());
}
public static void invokeAfterCommit(List<TransactionSynchronization> synchronizations) {
    if (synchronizations != null) {
      for (TransactionSynchronization synchronization : synchronizations) {
        synchronization.afterCommit();
      }
    }
}

上面会把缓存在 TransactionSynchronizationManager 中的 TransactionSynchronization 按顺序来执行 afterCommit 方法,其中 TransactionSynchronization 以集合形式缓存在 TransactionSynchronizationManager 的 ThreadLocal 中。



目录
相关文章
|
8月前
|
人工智能 运维 Java
Spring AI Alibaba Admin 开源!以数据为中心的 Agent 开发平台
Spring AI Alibaba Admin 正式发布!一站式实现 Prompt 管理、动态热更新、评测集构建、自动化评估与全链路可观测,助力企业高效构建可信赖的 AI Agent 应用。开源共建,现已上线!
7967 111
|
9月前
|
SQL Java 关系型数据库
Spring事务传播机制:7种姿势教你玩转"事务接力赛"
事务传播机制是Spring框架中用于管理事务行为的重要概念,它决定了在方法调用时事务如何传递与执行。通过7种传播行为,开发者可以灵活控制事务边界,适应不同业务场景。例如:REQUIRED默认加入或新建事务,REQUIRES_NEW独立开启新事务,NESTED支持嵌套回滚等。合理使用传播机制不仅能保障数据一致性,还能提升系统性能与健壮性。掌握这“七种人格”,才能在复杂业务中游刃有余。
|
8月前
|
NoSQL Java 数据库连接
《深入理解Spring》Spring Data——数据访问的统一抽象与极致简化
Spring Data通过Repository抽象和方法名派生查询,简化数据访问层开发,告别冗余CRUD代码。支持JPA、MongoDB、Redis等多种存储,统一编程模型,提升开发效率与架构灵活性,是Java开发者必备利器。(238字)
|
Java 关系型数据库 数据库
微服务——SpringBoot使用归纳——Spring Boot事务配置管理——常见问题总结
本文总结了Spring Boot中使用事务的常见问题,虽然通过`@Transactional`注解可以轻松实现事务管理,但在实际项目中仍有许多潜在坑点。文章详细分析了三个典型问题:1) 异常未被捕获导致事务未回滚,需明确指定`rollbackFor`属性;2) 异常被try-catch“吃掉”,应避免在事务方法中直接处理异常;3) 事务范围与锁范围不一致引发并发问题,建议调整锁策略以覆盖事务范围。这些问题看似简单,但一旦发生,排查难度较大,因此开发时需格外留意。最后,文章提供了课程源代码下载地址,供读者实践参考。
424 0
|
Java 关系型数据库 数据库
微服务——SpringBoot使用归纳——Spring Boot事务配置管理——Spring Boot 事务配置
本文介绍了 Spring Boot 中的事务配置与使用方法。首先需要导入 MySQL 依赖,Spring Boot 会自动注入 `DataSourceTransactionManager`,无需额外配置即可通过 `@Transactional` 注解实现事务管理。接着通过创建一个用户插入功能的示例,展示了如何在 Service 层手动抛出异常以测试事务回滚机制。测试结果表明,数据库中未新增记录,证明事务已成功回滚。此过程简单高效,适合日常开发需求。
1880 0
|
Java 数据库 微服务
微服务——SpringBoot使用归纳——Spring Boot事务配置管理——事务相关
本文介绍Spring Boot事务配置管理,阐述事务在企业应用开发中的重要性。事务确保数据操作可靠,任一异常均可回滚至初始状态,如转账、购票等场景需全流程执行成功才算完成。同时,事务管理在Spring Boot的service层广泛应用,但根据实际需求也可能存在无需事务的情况,例如独立数据插入操作。
352 0
|
JSON Java 数据格式
微服务——SpringBoot使用归纳——Spring Boot返回Json数据及数据封装——封装统一返回的数据结构
本文介绍了在Spring Boot中封装统一返回的数据结构的方法。通过定义一个泛型类`JsonResult&lt;T&gt;`,包含数据、状态码和提示信息三个属性,满足不同场景下的JSON返回需求。例如,无数据返回时可设置默认状态码&quot;0&quot;和消息&quot;操作成功!&quot;,有数据返回时也可自定义状态码和消息。同时,文章展示了如何在Controller中使用该结构,通过具体示例(如用户信息、列表和Map)说明其灵活性与便捷性。最后总结了Spring Boot中JSON数据返回的配置与实际项目中的应用技巧。
1016 0
|
JSON Java fastjson
微服务——SpringBoot使用归纳——Spring Boot返回Json数据及数据封装——使用 fastJson 处理 null
本文介绍如何使用 fastJson 处理 null 值。与 Jackson 不同,fastJson 需要通过继承 `WebMvcConfigurationSupport` 类并覆盖 `configureMessageConverters` 方法来配置 null 值的处理方式。例如,可将 String 类型的 null 转为 &quot;&quot;,Number 类型的 null 转为 0,避免循环引用等。代码示例展示了具体实现步骤,包括引入相关依赖、设置序列化特性及解决中文乱码问题。
707 0
|
JSON Java fastjson
微服务——SpringBoot使用归纳——Spring Boot返回Json数据及数据封装——Spring Boot 默认对Json的处理
本文介绍了在Spring Boot中返回Json数据的方法及数据封装技巧。通过使用`@RestController`注解,可以轻松实现接口返回Json格式的数据,默认使用的Json解析框架是Jackson。文章详细讲解了如何处理不同数据类型(如类对象、List、Map)的Json转换,并提供了自定义配置以应对null值问题。此外,还对比了Jackson与阿里巴巴FastJson的特点,以及如何在项目中引入和配置FastJson,解决null值转换和中文乱码等问题。
1811 0
|
10月前
|
Java 关系型数据库 数据库
深度剖析【Spring】事务:万字详解,彻底掌握传播机制与事务原理
在Java开发中,Spring框架通过事务管理机制,帮我们轻松实现了这种“承诺”。它不仅封装了底层复杂的事务控制逻辑(比如手动开启、提交、回滚事务),还提供了灵活的配置方式,让开发者能专注于业务逻辑,而不用纠结于事务细节。
1195 1