Spring中事务嵌套这么用一定得注意了!!
2023-04-22 11:20:56 来源:博客园
前言

最近项目上有一个使用事务相对复杂的业务场景报错了。在绝大多数情况下,都是风平浪静,没有问题。其实内在暗流涌动,在有些异常情况下就会报错,这种偶然性的问题很有可能就会在暴露到生产上造成事故,那究竟是怎么回事呢?

问题描述

我们用一个简单的例子模拟下,大家也可以看看下面这段代码输出的结果是什么。

在类SecondTransactionService定义一个简单接口transaction2,插入一个用户,同时必然会抛出错误
@Override@Transactional(rollbackFor = Exception.class)public void transaction2() {    System.out.println("do transaction2.....");    User user = new User("tx2", "111", 18);    // 插入一个用户    userService.insertUser(user);    // 跑错了    throw new RuntimeException();}
在另外一个类FirstTransactionService定义一个接口transaction1,它调用transaction2方法,同时做了try catch处理
@Override@Transactional(rollbackFor = Exception.class)public void transaction1() {    System.out.println("do transaction1 .......");    try {        // 调用另外一个事务,try catch住        secondTransactionService.transaction2();    } catch (Exception e) {        e.printStackTrace();    }    // 插入当前用户tx1    User user = new User("tx1", "111", 18);    userService.insertUser(user);}
定义一个controller,调用transaction1方法
@GetMapping("/testNestedTx")public String testNestedTx() {    firstTransactionService.transaction1();    return "success";}

大家觉得调用这个http接口,最终数据库插入的是几条数据呢?


(资料图片仅供参考)

问题结果

正确答案是数据库插入了0条数据。

同时控制台也报错了,报错原因是:org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only

是否和你预想的一样呢?你知道是为什么吗?

原因追溯

其实原因很简单,我们都知道,一个事务要么全成功提交事务,要么失败全部回滚。如果出现在一个事务中部分SQL要回滚,部分SQL要提交,这不就主打的一个”前后矛盾,精神分裂“吗?

controller.testNestedTx()   ||   / FirstTransactionService.transaction1()   REQUIRED隔离级别       ||        ||        || 捕获异常,提交事务,出错啦       / || FirstTransactionService.transaction2()   REQUIRED隔离级别       || ||        || 抛出异常,标记事务为rollback only       =======================
事务的隔离级别为REQUIRED,那么发现没有事务开启一个事务操作,有的话,就合并到这个事务中,所以transaction1()transaction2()是在同一个事务中。transaction2()抛出异常,那么事务会被标记为rollback only, 源码如下所示:transaction1()由于try catch 异常,正常运行,想必就要可以提交事务了,在提交事务的时候,会检查rollback标记,如果是true, 这时候就会抛出上面的异常了。源码如下图所示:

这下,是不是很清楚知道报错的原因了,那想想该怎么处理呢?

解决之道

知道了根本原因之后,是不是解决的方案就很明朗了,我们可以通过调整事务的传播方式分拆多个事务管理,或者让一个事务"前后一致",做一个诚信的好事务。

try catch放到内层事务中,也就是transaction2()方法中,这样内层事务会跟着外部事务进行提交或者回滚。
@Override    @Transactional(rollbackFor = Exception.class)    public void transaction2() {        try {            System.out.println("do transaction2.....");            User user = new User("tx2", "111", 18);            userService.insertUser2(user);            throw new RuntimeException();        } catch (Exception e) {            e.printStackTrace();        }    }
如果希望内层事务抛出异常时中断程序执行,直接在外层事务的catch代码块中抛出e,这样同一个事务就都会回滚。如果希望内层事务回滚,但不影响外层事务提交,需要将内层事务的传播方式指定为PROPAGATION_NESTEDPROPAGATION_NESTED基于数据库savepoint实现的嵌套事务,外层事务的提交和回滚能够控制嵌内层事务,而内层事务报错时,可以返回原始savepoint,外层事务可以继续提交。事务的传播机制

前面提到了事务的传播机制,我们再看都有哪几种。

PROPAGATION_REQUIRED:加入到当前事务中,如果当前没有事务,就新建一个事务。这是最常见的选择,也是Spring中默认采用的方式。PROPAGATION_SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。PROPAGATION_MANDATORY:支持当前事务,如果当前没有事务,就抛出异常。PROPAGATION_REQUIRES_NEW:新建一个事务,如果当前存在事务,把当前事务挂起。PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。PROPAGATION_NEVER: 以非事务方式执行,如果当前存在事务,则抛出异常。PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。

如何理解PROPAGATION_NESTED的传播机制呢,和PROPAGATION_REQUIRES_NEW又有什么区别呢?我们用一个例子说明白。

定义serviceA.methodA()PROPAGATION_REQUIRED修饰;定义serviceB.methodB()以表格中三种方式修饰;methodA中调用methodB;总结

在我的项目中之所以会报“rollback-only”异常的根本原因是代码风格不一致的原因。外层事务对错误的处理方式是返回true或false来告诉上游执行结果,而内层事务是通过抛出异常来告诉上游(这里指外层事务)执行结果,这种差异就导致了“rollback-only”异常。大家也可以去review自己项目中的代码,是不是也偷偷犯下同样的错误了。

欢迎关注个人公众号【JAVA旭阳】交流学习

Spring中事务嵌套这么用一定得注意了!!

2023-04-22

汇宇制药:4月21日融资买入265.9万元,融资融券余额2.21亿元

2023-04-22

全球热点评!2023安徽研学旅游大会在铜陵举行

2023-04-22

泰和县召开校园食品安全治理提升专项行动推进会

2023-04-22

孔冲

2023-04-22

高要二中地址_高要二中

2023-04-22

震有科技自研力铸造数智网络,助力5G新发展

2023-04-22

天天快讯:嘉泽新能:4月21日融券净卖出1.46万股,连续3日累计净卖出3.07万股

2023-04-22

中恒集团:4月21日融资净买入25.91万元,连续3日累计净买入665.21万元_世界报道

2023-04-22

当前热讯:也门踩踏至少85死322伤!有人未经批准分发现金,目击者:电线爆炸引发恐慌

2023-04-22

成都高新区第十一轮9-45岁扩龄九价HPV疫苗到苗通知_世界聚焦

2023-04-22

动力新科(600841.SH)控股股东上汽集团持股比例降至38.86% 当前通讯

2023-04-22

全球微动态丨三六零去年安全业务实现营收17.91亿元

2023-04-22

抖音怎样认证企业号要多少钱_申请抖音号企业认证要多少费用_环球速读

2023-04-22

妊娠纹长什么样子_妊娠纹长什么样|天天看点

2023-04-22

世界热资讯!高盛“巾帼圆梦”中国女企业家调查:七成受访者认为缺乏人才是企业创新的最大挑战

2023-04-22

北大街小学举行读书节活动

2023-04-22

“重启关系”,卢拉开启访欧之旅

2023-04-22

院校代号四位数 查询2021_院校代号四位数|当前看点

2023-04-22

AI画笔远程涂色块、笑脸墙展示各行各业的普通劳动者……“时光博物馆”

2023-04-22

“燃油车让位电动车”?一汽-大众用实力捍卫用户的技术路线选择

2023-04-22

快船表示很无奈!蒙蒂居然主动弃用了自己的心腹爱将?

2023-04-22

绿豆白鸽汤可以祛痘吗(绿豆白鸽汤的功效做法)

2023-04-22

信息:百利天恒涨10.98%

2023-04-22

每日精选:信阳职业技术学院第十七届大学生田径运动会开幕

2023-04-22

速讯:花旗:予越秀地产(00123)“买入”评级 目标价14.2港元

2023-04-22

世界实时:短姑圣迹

2023-04-22

全球快资讯:绝命错杀令_关于绝命错杀令介绍

2023-04-22

骑士卡加油怎么免费申请(骑士卡加油怎么用)

2023-04-22

森林超市500字优秀作文(优选32篇)

2023-04-22

财报速递:上海贝岭2023年一季度净利润3282.63万元,总体财务状况一般

2023-04-21

大方:产销两旺 万亩樱桃喜获丰收

2023-04-21

2023 中国好 SaaS 大赛路演 - 数位拓店云 全球热点

2023-04-21

热讯:刘安坤2023年一季度表现,融通逆向策略灵活配置混合A基金季度涨幅3.45%

2023-04-21

元成股份:硅密(常州)电子设备有限公司产品和业务尚未涉及光刻胶领域,感谢!-最资讯

2023-04-21

天天快报!直男癌是什么意思网络语_直男癌是什么意思

2023-04-21

立方图形_立方图

2023-04-21

如何煮黑米-快消息

2023-04-21

宜尚酒店展现强劲竞争力,在成都斩获优质业绩与口碑

2023-04-21

高速反辐射导弹_关于高速反辐射导弹简述

2023-04-21

全球速递!国家外汇管理局:科技创新发展、服务业的扩大开放等领域的外资流入会明显增多

2023-04-21

天天观天下!嘉欣丝绸营收净利双丰收 连续13年派现 累计金额超11亿

2023-04-21

当前快报:刮风时为什么会发出嗖嗖的声响

2023-04-21

我要去哪里是谁唱的_我要去哪里_环球简讯

2023-04-21

美股三大股指小幅收跌 新能源车板块普跌

2023-04-21

天天日报丨上海航空服务学校2021年招生计划_上海市航空服务学校官网

2023-04-21

全球播报:喝玫瑰花茶有什么好处或疗效_喝玫瑰花茶有什么好处

2023-04-21

消费曝光台丨“标准车位”车进得去、人出不来,涉事开发商遭投诉 世界热头条

2023-04-21

新股优品车暴涨370%!造车新势力再度大跌

2023-04-21

当前速递!世界上最快的SFF显卡进入零售市场

2023-04-21

全球资讯:“长缆科技孟加拉玛格丽特三期项目500kV电缆终端工程”顺利通过验收试验

2023-04-21

世界观速讯丨2023运城市医保卡怎么查余额明细呢?医保卡查询方法如下

2023-04-21

城市里的“守书人”:只为人与书的惊喜相遇

2023-04-21

【机构评级】 花旗:予越秀地产(00123)“买入”评级 目标价14.2港元

2023-04-21

快递续重是一斤还是一公斤(快递续重是按一公斤起算的)-焦点速读

2023-04-21

环球消息!国家外汇管理局:一季度人民币汇率双向波动小幅升值 在全球表现来看是相对稳健的

2023-04-21

将论文写在田野上 武汉7名乡村人才获评“副教授”_报资讯

2023-04-21

初一数学找规律题及答案

2023-04-21

联想刘军:“以服务为导向转型”取得阶段性成果

2023-04-21

如何开展高质量跨学科学习(上) 环球新动态

2023-04-21

当前滚动:如何彻底关闭微信群消息提醒(怎样关微信群消息提醒) 全球快报

2023-04-21

北京市中小学生科技创客活动举办

2023-04-21

世界新资讯:濮耐股份董秘回复:公司目前没有产品应用到固态储氢

2023-04-21

以项目化学习重构中考复习生态 全球快看点

2023-04-21

奇式网盾吧_奇式网盾没用 环球时讯

2023-04-21

微头条丨百诚医药:4月20日融资买入757.75万元,融资融券余额1.68亿元

2023-04-21

环球聚焦:小萨:G3将是系列赛中最艰难的一场 系列赛才刚刚开始

2023-04-21

中信建投:供应受限消费维持高增,重视锂价底部布局机会

2023-04-21

美联储鹰派官员Mester暗示支持再次加息 但也敦促要谨慎行事

2023-04-21

东胜·天御 | 五一让利,8重豪礼城央叠享

2023-04-21

多方助力安家落户 武汉市江岸司法局倾心帮扶刑释人员 天天通讯

2023-04-21

世界播报:100%命中率拿下10分,快船后场大将值得更高的战术地位?

2023-04-21

每日热闻!工信部:重点规范APP“摇一摇”“乱跳转”等热点问题

2023-04-21

直播:纳斯达克收跌-0.80%_环球微头条

2023-04-21

学好语文的重要性作文800字_学习语文的重要性作文 当前热门

2023-04-21

敢拍!《检察风云》连上10个热搜,我断言:中国电影前进了一大步|环球快讯

2023-04-21

焦点速看:民营企业发展特写:转变、创新、追求

2023-04-21

世界热消息:这国提议欧盟对俄罗斯实施新一轮制裁

2023-04-21

探访伊利现代智慧健康谷-天天看热讯

2023-04-21

阿根廷的足球明星有哪些_阿根廷有哪些足球明星

2023-04-21

环球观热点:被“驯服”的厅官沦为“烟酒老板” 基本情况讲解

2023-04-21

广汽埃安李俊斌:保持先进制造能力以及质量管控能力 环球新动态

2023-04-21

043期何飞大乐透预测奖号:前区胆码参考

2023-04-21

订飞机票网站_定机票网

2023-04-21

0-4!2-3!1-4!三大豪门轰然坍塌,拒绝引进欧冠之王,自讨苦吃_世界观点

2023-04-21

通许县朱砂镇:春季“洗街”行动 让朱砂更靓丽|全球热消息

2023-04-21

越秀地产(00123.HK):公司股份和债券将于下午一时复牌

2023-04-21

农发行山东省分行营业部举办第二届三人制篮球|全球快消息

2023-04-21

恒而达(300946)报收于31.66元,下跌1.4%

2023-04-21

环球滚动:江苏昆山中学:用“心”护航学子追梦之旅

2023-04-21

环球微资讯!刚刚,央行重磅发声!信息量巨大!

2023-04-21

厦门见证补贴多少钱?附补贴标准

2023-04-21

【聚看点】2023广州公共就业服务岗位补贴能与其他岗位补贴同时享受吗?

2023-04-21

环球短讯!面团揉不光滑总是开裂(面团揉不光滑总是开裂怎么办)

2023-04-21

华为宣布实现自主可控的MetaERP研发和替换

2023-04-21

今日原油行情走势分析:欧佩克+减产安排的短期挤压可能正在失去动力|天天快消息

2023-04-21

【国际漫评】拥枪教育从娃娃抓起?

2023-04-21

天天新消息丨迷你世界海洋版本怎么做刷怪塔 迷你世界刷怪塔制作方法一览

2023-04-20

韩国:到2030年将投资20万亿韩元用于蓄电池研发 全球百事通

2023-04-20

2023年高端数控机床行业市场调研分析

2023-04-20