从嵌套事务的日志看MyBatis的sqlSession生命周期

service层业务代码

@Override
public void test(){QueryWrapper<StoreRebateCalculateLog> queryWrapper;queryWrapper = new QueryWrapper<>();queryWrapper.eq("delete_flag", 0);//执行查询A,A事务开启List<StoreRebateCalculateLog> storeRebateCalculateLogs = storeRebateCalculateLogDao.selectBatchIds(Arrays.asList(90010, 90011, 90012, 90013));//更新,开启B事务((StoreRebateCalculateLogServiceImpl) AopContext.currentProxy()).updateTest(storeRebateCalculateLogs);//取当前类的代理对象执行,保证在同一个类中的@Transactional注解能够生效
}@Transactional(rollbackFor = Exception.class)
public void updateTest(List<StoreRebateCalculateLog> storeRebateCalculateLogs1) {for (StoreRebateCalculateLog log: storeRebateCalculateLogs1) {log.setNeedRepeatCalFlag("0");this.storeRebateCalculateLogDao.updateById(log);}
}

这里先执行一个查询,然后更新操作。查询的方法是一个事务A,后面执行更新操作的方法updateTest因为采用了声明式事务,会重新开启事务,这里记为是事务B。

查看调试模式下的MyBatis执行日志

//创建sqlSession A
Creating a new SqlSession  
//为A注册事务    
Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@8d867b]
JDBC Connection [HikariProxyConnection@8519751 wrapping com.mysql.cj.jdbc.ConnectionImpl@2c5cdd] will be managed by Spring
==>  Preparing: SELECT calculate_log_id,month_str,day_str,total_count,min_id,max_id,status,need_repeat_cal_flag,delete_flag,creation_date,created_by,version_num,last_update_date,last_updated_by,last_update_login FROM store_rebate_calculate_log WHERE calculate_log_id IN ( ? , ? , ? , ? ) AND delete_flag=0
==> Parameters: 90010(Integer), 90011(Integer), 90012(Integer), 90013(Integer)
<==    Columns: calculate_log_id, month_str, day_str, total_count, min_id, max_id, status, need_repeat_cal_flag, delete_flag, creation_date, created_by, version_num, last_update_date, last_updated_by, last_update_login
<==        Row: 90010, 2024-03, 20240308, 0, null, null, 2, 1, 0, 2024-03-14 22:20:09, 62169, 9, 2024-03-17 08:40:44, 62169, 62169
<==        Row: 90011, 2024-03, 20240309, 0, null, null, 2, 1, 0, 2024-03-14 22:20:09, 62169, 9, 2024-03-17 08:41:45, 62169, 62169
<==        Row: 90012, 2024-03, 20240310, 0, null, null, 2, 1, 0, 2024-03-14 22:20:09, 62169, 9, 2024-03-17 08:41:45, 62169, 62169
<==        Row: 90013, 2024-03, 20240311, 0, null, null, 2, 1, 0, 2024-03-14 22:20:10, 62169, 2, 2024-03-14 23:34:23, 62169, 62169
<==      Total: 4
//释放sqlSession A    
Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@8d867b]
//挂起sqlSession A
Transaction synchronization suspending SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@8d867b]//创建sqlSession B    
Creating a new SqlSession
//为B注册事务      
Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@10c1754]
JDBC Connection [HikariProxyConnection@25084448 wrapping com.mysql.cj.jdbc.ConnectionImpl@1e088a3] will be managed by Spring
==>  Preparing: UPDATE store_rebate_calculate_log SET month_str=?, day_str=?, total_count=?, status=?, need_repeat_cal_flag=?, creation_date=?, created_by=?, version_num=?, last_update_date=?, last_updated_by=?, last_update_login=? WHERE calculate_log_id=? AND version_num=? AND delete_flag=0
==> Parameters: 2024-03(String), 20240308(String), 0(Integer), 2(String), 0(String), 2024-03-14 22:20:09.0(Timestamp), 62169(Integer), 10(Integer), 2024-03-17 09:56:44.399(Timestamp), 62169(Integer), 62169(Integer), 90010(Long), 9(Integer)
<==    Updates: 1
Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@10c1754]
Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@10c1754] from current transaction
==>  Preparing: UPDATE store_rebate_calculate_log SET month_str=?, day_str=?, total_count=?, status=?, need_repeat_cal_flag=?, creation_date=?, created_by=?, version_num=?, last_update_date=?, last_updated_by=?, last_update_login=? WHERE calculate_log_id=? AND version_num=? AND delete_flag=0
==> Parameters: 2024-03(String), 20240309(String), 0(Integer), 2(String), 0(String), 2024-03-14 22:20:09.0(Timestamp), 62169(Integer), 10(Integer), 2024-03-17 09:56:44.415(Timestamp), 62169(Integer), 62169(Integer), 90011(Long), 9(Integer)
<==    Updates: 1
//这里省略了一部分更新操作的日志....//释放sqlSession B   
Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@10c1754]
//提交sqlSession B       
Transaction synchronization committing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@10c1754]
//注销sqlSession B       
Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@10c1754]
//关闭sqlSession B    
Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@10c1754]//恢复sqlSession A    
Transaction synchronization resuming SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@8d867b]
//注销sqlSession A  
Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@8d867b]
//关闭sqlSession A     
Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@8d867b]

可以得出下面的流程图

image-20240317104042175

另外需要注意的是,如果上面的test()方法也加上@Transactional注解,结果会是一样吗?

即如下的代码:

@Override
@Transactional(rollbackFor = Exception.class) //这里的区别
public void test(){QueryWrapper<StoreRebateCalculateLog> queryWrapper;queryWrapper = new QueryWrapper<>();queryWrapper.eq("delete_flag", 0);//执行查询A,A事务开启List<StoreRebateCalculateLog> storeRebateCalculateLogs = storeRebateCalculateLogDao.selectBatchIds(Arrays.asList(90010, 90011, 90012, 90013));//更新((StoreRebateCalculateLogServiceImpl) AopContext.currentProxy()).updateTest(storeRebateCalculateLogs);//取当前类的代理对象执行,保证在同一个类中的@Transactional注解能够生效
}@Transactional(rollbackFor = Exception.class)
public void updateTest(List<StoreRebateCalculateLog> storeRebateCalculateLogs1) {for (StoreRebateCalculateLog log: storeRebateCalculateLogs1) {log.setNeedRepeatCalFlag("0");this.storeRebateCalculateLogDao.updateById(log);}
}

跟踪日志发现:

//这里只截取中间部分有差异的日志
==>  Preparing: SELECT calculate_log_id,month_str,day_str,total_count,min_id,max_id,status,need_repeat_cal_flag,delete_flag,creation_date,created_by,version_num,last_update_date,last_updated_by,last_update_login FROM store_rebate_calculate_log WHERE calculate_log_id IN ( ? , ? , ? , ? ) AND delete_flag=0
==> Parameters: 90010(Integer), 90011(Integer), 90012(Integer), 90013(Integer)
<==    Columns: calculate_log_id, month_str, day_str, total_count, min_id, max_id, status, need_repeat_cal_flag, delete_flag, creation_date, created_by, version_num, last_update_date, last_updated_by, last_update_login
<==        Row: 90010, 2024-03, 20240308, 0, null, null, 2, 1, 0, 2024-03-14 22:20:09, 62169, 11, 2024-03-17 10:46:48, 62169, 62169
<==        Row: 90011, 2024-03, 20240309, 0, null, null, 2, 1, 0, 2024-03-14 22:20:09, 62169, 11, 2024-03-17 10:47:55, 62169, 62169
<==        Row: 90012, 2024-03, 20240310, 0, null, null, 2, 1, 0, 2024-03-14 22:20:09, 62169, 11, 2024-03-17 10:48:03, 62169, 62169
<==        Row: 90013, 2024-03, 20240311, 0, null, null, 2, 1, 0, 2024-03-14 22:20:10, 62169, 4, 2024-03-17 10:48:03, 62169, 62169
<==      Total: 4
Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1f057a7]//发现这里更新时是从当前的会话中取的sqlSession,用的是同一个sqlSession,没有创建新的sqlSession
Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1f057a7] from current transaction
==>  Preparing: UPDATE store_rebate_calculate_log SET month_str=?, day_str=?, total_count=?, status=?, need_repeat_cal_flag=?, creation_date=?, created_by=?, version_num=?, last_update_date=?, last_updated_by=?, last_update_login=? WHERE calculate_log_id=? AND version_num=? AND delete_flag=0
==> Parameters: 2024-03(String), 20240308(String), 0(Integer), 2(String), 0(String), 2024-03-14 22:20:09.0(Timestamp), 62169(Integer), 12(Integer), 2024-03-17 11:21:30.178(Timestamp), 62169(Integer), 62169(Integer), 90010(Long), 11(Integer)
<==    Updates: 1
Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1f057a7]

从日志可以发现后面更新时是从当前的会话中取的sqlSession,用的是同一个sqlSession,没有创建新的sqlSession,这是什么原因呢?

因为在调用的方法test()加上@Transactional注解后,其实省略了propagation属性,而propagation的默认值就是 Propagation.REQUIRED,也就是说如果当前开启了事务,就不会创建新的事务。

其实上面的注解相当于

 @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)

所以才有了上面的结果。

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

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

相关文章

股票买卖问题:状态定义的误解与思考

文章目录 问题状态的定义与理解状态定义状态转移函数困惑思考 反思参考资料 问题 股票买卖问题是动态规划中常考的题型&#xff0c;题目一般是给一个 p r i c e s prices prices的数组&#xff0c;每个元素代表当天的股票价格&#xff0c;再给你一个 k k k值&#xff0c;代表允…

pycharm 历史版本下载地址

pycharm 历史版本下载地址 老版本能用就行&#xff0c;不需要搞最新的&#xff0c;当然了&#xff0c;有些小伙伴就是喜欢新的&#xff08;最先吃螃蟹&#xff09; 博主就不搞最新了&#xff0c;哈哈 上菜&#xff1a; https://www.jetbrains.com/pycharm/download/other.html…

01初识Python

一、Python 简介 二、为什么要学Python? 三、Python 安装 四、输出第一条指令 五、总结 一、Python 简介 Python是一种高级编程语言,由Guido van Rossum于1991年创建。它具有简单易学的语法结构,被广泛应用于Web开发、数据科学、人工智能等领域。 Python具有丰富的库…

Windows→Linux,本地同步到服务器

适用背景&#xff1a; 用自己电脑修改代码&#xff0c;使用实验室/公司的服务器炼丹的朋友 优势&#xff1a; 本地 <--> 服务器&#xff0c;实时同步&#xff0c;省去文件传输的步骤 本地改 -> 自动同步到服务器 -> 服务器跑代码 -> 一键同步回本地&#xff…

瑞熙贝通打造智慧校园实验室安全综合管理平台

一、建设思路 瑞熙贝通实验室安全综合管理平台是基于以实验室安全&#xff0c;用现代化管理思想与人工智能、大数据、互联网技术、物联网技术、云计算技术、人体感应技术、语音技术、生物识别技术、手机APP、自动化仪器分析技术有机结合&#xff0c;通过建立以实验室为中心的管…

给你的H5页面加上惯性滚动吧!

在移动端&#xff0c;如果你使用过 overflow: scroll 生成一个滚动容器&#xff0c;会发现它的滚动是比较卡顿&#xff0c;呆滞的。为什么会出现这种情况呢&#xff1f; 因为我们早已习惯了目前的主流操作系统和浏览器视窗的滚动体验&#xff0c;比如滚动到边缘会有回弹&#…

《C缺陷和陷阱》-笔记(5)

目录 一、整数溢出 溢出 如何防止溢出 二、为函数main提供返回值 连接 一、什么是连接器 连接器工作原理 三、声明与定义 四、命名冲突与static 修饰符 statia 一、整数溢出 溢出 C语言中存在两类整数算术运算&#xff0c;有符号运算与无符号运算。 在无…

Redisinsight默认端口改成5540了!网上的8001都是错误的

Redisinsight 打开白屏解决方法 最近发现一个很讨厌的bug&#xff0c;就是redisinsight运行之后&#xff0c;不行了&#xff0c;在网上找到的所有资料里面&#xff0c;redis insight都是运行在8001端口&#xff0c;但是我现在发现&#xff0c;变成了5540 所以对应的docker-com…

七.pandas处理第三方数据

目录 七.pandas处理第三方数据 1.Pandas读取文件 1.1 csv文件操作 1.1.1 CSV文件读取 自定义索引(inde_col) 查看每一列的dtype 更改文件标头名(列的标签) 跳过指定的行数 1.1.2 CSV文件写入 1.2 Excel文件操作 1.2.1 Excel文件读取 1.2.2 Excel文件写入 1.3 SQL操…

mysdql 启动错误 unknown variable windows phpstudy mysql错误日志的正确文件名

1. windowsphpstudy mysql错误日志的正确文件名 log-error"D:/phpstudy_pro/Extensions/MySQL5.7.26/data"。 刚好 数据库文件目录也是"D:/phpstudy_pro/Extensions/MySQL5.7.26/data" 其实对应的错误日志是 D:/phpstudy_pro/Extensions/MySQL5.7.26/dat…

web开发模式

1. Web 开发模式 目前主流的 Web 开发模式有两种&#xff0c;分别是 ① 基于服务器渲染的传统 Web 开发模式 ② 基于前后端分离的新型 Web 开发模式 1. 服务器渲染的Web开发模式 服务器渲染的概念&#xff1a;服务器发送给客户端的 HTML 页面&#xff0c;是在服务器通过字符…

【C++】类和对象终章

&#x1f525;博客主页&#xff1a; 小羊失眠啦. &#x1f3a5;系列专栏&#xff1a;《C语言》 《数据结构》 《C》 《Linux》 《Cpolar》 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 文章目录 一、初始化列表1.1 初始化列表的形式1.2 初始化列表的注意事项 二、explicit关键…

[数据集][目标检测]螺丝螺母检测数据集VOC+YOLO格式2100张13类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;2100 标注数量(xml文件个数)&#xff1a;2100 标注数量(txt文件个数)&#xff1a;2100 标注…

@RequestParam、@PathVariable、@RequestBody

1、中文翻译 RequestParam-请求参数、PathVariable-路径变量、RequestBody请求体 2、作用&#xff1a; Controller中获取前端传递的参数 3、从注解本身角度分析 3.1、PathVariable&#xff1a;路径变量 通过 PathVariable 可以将URL中占位符参数{xxx}绑定到处理器类的方法形…

CSS3病毒病原体图形特效

CSS3病毒病原体图形特效&#xff0c;源码由HTMLCSSJS组成&#xff0c;双击html文件可以本地运行效果&#xff0c;也可以上传到服务器里面 下载地址 CSS3病毒病原体图形特效代码

(二)移植FreeRTOS到STM32中

一、概念 &#xff08;1&#xff09;任务&#xff08;线程&#xff09;&#xff1a;根据功能的不同&#xff0c;将一个系统分割成一个个独立且无法返回的函数&#xff0c;这个函数就被称为任务 &#xff08;2&#xff09;任务栈&#xff1a;静态创建的任务保存在栈中 &#xf…

代码随想录阅读笔记-哈希表【四数相加II】

题目 给定四个包含整数的数组列表 A , B , C , D ,计算有多少个元组 (i, j, k, l) &#xff0c;使得 A[i] B[j] C[k] D[l] 0。 为了使问题简单化&#xff0c;所有的 A, B, C, D 具有相同的长度 N&#xff0c;且 0 ≤ N ≤ 500 。所有整数的范围在 -2^28 到 2^28 - 1 之间…

Formate函数的一般使用

Program Project2;{$APPTYPE CONSOLE}UsesSysUtils;Varnum: Integer;r1: Real;BeginRead(num, r1);Writeln(Format(%d 绝对值%%d&#xff1a;%d, [num, abs(num)]));Writeln(Format(%u 绝对值%%u&#xff1a;%u, [num, abs(num)]));Writeln(Format(%f 参数为浮点数&#xff0c;…

前后端分离:现代Web开发的协作模式

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

el-cascader修改样式(不影响全局)

当用/deep/想像往常一样修改&#xff0c;会发现不生效&#xff0c;原因在于这个组件和div#app同级了&#xff0c;如果去掉scoped&#xff0c;是最简单的方法&#xff0c;当然&#xff0c;为了不影响全局我们当然不能这么做。 以下是步骤&#xff1a; 1.我们查看组件属性&…