事务与异步方法(@Async)协同工作

目录

1. 问题场景与风险

(1)典型场景

(2)风险分析

2. 解决方案:事务提交后触发异步操作

(1)代码示例

(2)关键注解

3. 原理解析

(1)事务同步机制

(2)执行流程

4. 优化方案:@TransactionalEventListener

(1)定义事件

(2)发布事件

(3)监听事件

(4)优势

5. 注意事项

(1)事务传播与隔离

(2)异常处理

(3)线程上下文

6. 总结


当异步方法(@Async)在事务(@Transactional)上下文中被调用时,事务的提交与异步方法的执行顺序会直接影响数据一致性。

异步方法需要在事务提交后执行。

1. 问题场景与风险

(1)典型场景
  • 主方法:包含数据库操作,使用 @Transactional 管理事务。
  • 异步方法:在事务提交后执行,如发送通知、更新缓存等。
@Transactional
public void mainMethod() {//1. 数据库操作(如插入数据)repository.save(entity);//2. 调用异步方法asyncService.sendNotification(entity.getId());//可能未提交事务!
}
(2)风险分析
  • 异步方法在事务提交前执行:由于事务提交发生在主方法返回后,异步方法可能读取到未提交的数据,导致脏读或操作失败。
  • 数据不一致:若事务回滚,异步方法已执行的操作无法自动回滚。

2. 解决方案:事务提交后触发异步操作

通过 TransactionSynchronizationManager 注册事务同步回调,确保异步方法在事务提交后执行。

(1)代码示例
@Transactional
public void mainMethod() {// 1. 数据库操作FileInfo fileInfo = fileRepository.save(new FileInfo());// 2. 注册事务提交后的回调TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {@Overridepublic void afterCommit() {//事务提交后执行异步方法fileInfoService.transferFileAsync(fileInfo.getFileId(), webUserDto);}});
}
(2)关键注解
  • @Async 方法需独立于事务:确保异步方法本身不参与当前事务。
  • 避免事务传播:异步方法的事务传播级别应为 REQUIRES_NEW(若需独立事务)。

3. 原理解析

(1)事务同步机制
  • TransactionSynchronization:Spring 提供的事务同步接口,允许在事务的关键阶段(如提交、回滚)插入自定义逻辑。
  • afterCommit:事务成功提交后触发,此时数据已持久化到数据库。
(2)执行流程
  1. 主方法执行:数据库操作进入事务,但未提交。
  2. 注册回调:通过 registerSynchronization 注册 afterCommit 钩子。
  3. 事务提交:主方法退出,事务提交。
  4. 触发异步方法afterCommit 中调用异步方法,确保数据可见性。

4. 优化方案:@TransactionalEventListener

Spring 4.2+ 提供了更简洁的事务事件监听机制,替代手动注册 TransactionSynchronization

(1)定义事件
public class FileTransferEvent {private String fileId;private WebUserDto webUserDto;// 构造方法、Getter/Setter
}
(2)发布事件
@Transactional
public void mainMethod() {FileInfo fileInfo = fileRepository.save(new FileInfo());// 发布事件(事务提交后触发)applicationEventPublisher.publishEvent(new FileTransferEvent(fileInfo.getFileId(), webUserDto));
}
(3)监听事件
@Async
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void handleFileTransferEvent(FileTransferEvent event) {fileInfoService.transferFile(event.getFileId(), event.getWebUserDto());
}
(4)优势
  • 解耦:将事务提交后的逻辑与主方法分离。
  • 简化代码:无需手动管理事务同步器。
  • 灵活触发:支持按事务阶段(提交、回滚等)监听事件。

5. 注意事项

(1)事务传播与隔离
  • 异步方法的事务:若异步方法需要操作数据库,应使用 @Transactional(propagation = Propagation.REQUIRES_NEW) 启动新事务。
  • 避免长事务:异步方法不应阻塞,以免影响主线程性能。
(2)异常处理
  • 事务回滚:若主方法事务回滚,afterCommit@TransactionalEventListener 不会触发。
  • 异步方法异常:通过 AsyncUncaughtExceptionHandler 捕获异步方法中的异常。
(3)线程上下文

ThreadLocal 数据:事务上下文(如 SecurityContext)默认不传递到异步线程,需手动传递:

SecurityContext context = SecurityContextHolder.getContext();
CompletableFuture.runAsync(() -> {SecurityContextHolder.setContext(context);// 执行业务逻辑
});

6. 总结

  • 核心方案:通过事务同步器(TransactionSynchronization)或 @TransactionalEventListener 确保异步方法在事务提交后执行。
  • 最佳实践
    1. 使用 @TransactionalEventListener(phase = AFTER_COMMIT) 简化代码。
    2. 异步方法避免依赖未提交事务的数据。
    3. 合理配置事务传播和线程上下文。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/72424.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

关于进程的实验(子进程和父进程相关的)

文章目录 1.第一个问题2.第二个问题3.第三个问题 1.第一个问题 编写一段程序,利用系统调用fork( )创建两个进程。当此程序运行时,在系统中有一个父进程和两个子进程活动。让每一个进程在屏幕上显示一个字符:父进程显示字符“a”;子进程分别显…

MyBatis 如何创建 SqlSession 对象的?

MyBatis 创建 SqlSession 对象的过程主要由 SqlSessionFactory 接口及其实现类来完成。以下是详细步骤: 1. SqlSessionFactory 接口: SqlSessionFactory 是 MyBatis 的核心接口之一,它负责创建 SqlSession 对象。 你可以将 SqlSessionFactory 视为 Sql…

深度优先搜索(DFS)剪枝技术详解与C++实现

深度优先搜索(DFS)剪枝技术通过提前终止无效路径的搜索,大幅提升算法效率。以下是五种核心剪枝技术的详细解析及C代码示例: 目录 一、可行性剪枝 C实现示例 二、搜索顺序剪枝 伪代码逻辑 三、最优性剪枝 C实现示例 四、排除…

【双指针】移动零

题目描述: 算法分析: 观察输入输出: 输出中一共分为两个区域,0区和非零区。 但是在处理未完成之前,必然存在着一个零和非零数共存的区域,所以在处理的过程当中一共有三个区域,0区,…

学习15天:pytest

1、.pytest强大的插件 pytest-html(生成html格式的自动化测试报告) pytest-xdist测试用例分布式执行。多CPU分发。 pytest-ordering 用于改变测试用例的执行顺序 pytest-rerunfailures用例失败后重跑 allure-pytest 用于生成美观的测试报告。 2、规则: 模块…

股票交易所官方api接口有哪些?获取和使用需要满足什么条件

炒股自动化:申请官方API接口,散户也可以 python炒股自动化(0),申请券商API接口 python炒股自动化(1),量化交易接口区别 Python炒股自动化(2):获取…

2.7 滑动窗口专题:串联所有单词的子串

LeetCode 30. 串联所有单词的子串算法对比分析 1. 题目链接 LeetCode 30. 串联所有单词的子串 2. 题目描述 给定一个字符串 s 和一个字符串数组 words,words 中所有单词长度相同。要求找到 s 中所有起始索引,使得从该位置开始的连续子串包含 words 中所…

【区块链】区块链密码学基础

🌈个人主页: 鑫宝Code 🔥热门专栏: 闲话杂谈| 炫酷HTML | JavaScript基础 ​💫个人格言: "如无必要,勿增实体" 文章目录 区块链密码学基础引言一、哈希函数1.1 基本概念1.2 数学表达 二、非对称加密2.1…

Spring Boot配置类原理、Spring Boot核心机制理解,以及实现自动装置的底层原理

目的:从底层源码角度分析 Spring Boot 配置类以及自动装载的底层原理 文章目录 1. Spring Boot 配置类实现自动装载1.1 @Configuration注解1.2 @Configuration 注解完成 bean 注入流程图1.3 @ConfigurationProperties注解赋值2. Spring Boot的核心机制:自动装配2.1 @SpringBo…

docker桌面版启动redis,解决无法连接

docker run -d --name redis -p 6379:6379 -v E:\2\redis\redis.conf:/usr/local/etc/redis/redis.conf redis redis-server /usr/local/etc/redis/redis.conf 在本地创建一个目录,里面有个redis.conf文件,内容如下,启动时绑定这个配置文件目…

[网络][tcp协议]:tcp报头

tcp(传输控制协议)是一种面向字节流的传输层协议,相较于udp协议,tcp能保证传输数据的可靠性与准确性,tcp也是目前最常见的传输层协议 本文主要介绍tcp报头各个字段的含义与用途 注:保留6位和6位标记位是目前最普遍的写法,在我查资料时,发现有一些拓展情况,会在后文细说 最简单的…

【虚幻C++笔记】引擎源码下载及编译步骤

目录 1.在GitHub上访问虚幻引擎源代码2.安装Visual Studio 20223.解压完成以后,打开源码的根目录,选择Setup.bat运行4.选择GenerateProjectFiles.bat运行,生成uE5.sln文件,点击这个文件打开项目5.设置编译的选项,选择DevelopmentE…

【数学建模】层次分析法(AHP)详解及其应用

层次分析法(AHP)详解及其应用 引言 在现实生活和工作中,我们经常面临复杂的决策问题,这些问题通常涉及多个评价准则,且各准则之间可能存在相互影响。如何在这些复杂因素中做出合理的决策?层次分析法(Analytic Hierarchy Process…

科普:为何要对特征进行分箱?

一、为何要对特征进行分箱? 分箱(Binning)是将连续型或离散型特征转化为区间型变量的过程,其核心目标是提升模型效果和解释性,具体原因如下: 1. 业务需求 可解释性:将特征转化为业务可理解的…

理解langgraph工作流的驱动逻辑,以适应langgraph工作流模式的编程。

langgraph的工作流模式虽然方便直观,但习惯了普通函数式编程的数据流处理。刚开始接触时,确实容易试图用函数式编程的思维去适配它,特别是langgraph数据传递由状态字典管理,而非函数返回值,导致代码不够自然&#xff0…

线性dp(数字三角形,LIS,LCS,LCIS)

文章目录 线性dp数字三角形题目思路 LIS(最长上升子序列)代码(n^2)二分优化(nlogn) LCS(最长公共子序列)代码 LCS——>>LIS思路代码 最长公共子串最长公共上升子序列(LCIS) 线…

Spring Validation参数校验

Spring Validation是Spring框架中用于数据校验的核心模块&#xff0c;通过注解简化数据校验逻辑。 1. 依赖引入&#xff08;SpringBoot项目&#xff09; Spring Boot项目&#xff1a;自动包含spring-boot-starter-validation <dependency><groupId>org.springfra…

《AI大模型趣味实战》No2 : 快速搭建一个漂亮的AI家庭网站-相册/时间线/日历/多用户/个性化配色(中)

快速搭建一个漂亮的AI家庭网站-相册/时间线/日历/多用户/个性化配色(中) 摘要 在上一篇文章中&#xff0c;我们介绍了如何搭建一个基础的家庭网站&#xff08;V1.0版本&#xff09;&#xff0c;包含了用户管理、相册管理、时间线和日历等功能。本文将继续深入&#xff0c;详细…

pythonSTL---sys

sys 是 Python 标准库中的一个内置模块&#xff0c;它提供了许多与 Python 解释器和系统环境进行交互的功能。 sys方法 1. 导入 sys 模块 在使用 sys 库的功能之前&#xff0c;需要先导入它&#xff1a; import sys2. 命令行参数 (sys.argv) sys.argv 是一个包含命令行参数…

软件需求分类、需求获取(高软46)

系列文章目录 软件需求分类&#xff0c;需求获取 文章目录 系列文章目录前言一、软件需求二、获取需求三、真题总结 前言 本节讲明软件需求分类、需求获取的相关知识。 一、软件需求 二、获取需求 三、真题 总结 就是高软笔记&#xff0c;大佬请略过&#xff01;