Spring嵌套事务异常Transaction rolled back because it has been marked as rollback-only
项目场景:
在循环里面使用try-catch去捕获异常的时候,并且try里面调的方法它也使用了事务注解 @transactional或者用了事务切面AOP去实现方法事务注入
问题描述
我这里的业务需求是A方法里面调了B方法,并且A和B都有事务,当B出现异常的时候我想获取B的具体报错信息,但是catch这个B方法的时候发生了嵌套事务异常,A方法继续往上抛出导致Transaction rolled back because it has been marked as rollback-only(事务回滚,因为它已被标记为仅回滚)
示例代码如下:
@transactionalpublic void A(){try{B();}catch(Exception e){e.printStackTrace();}}@transactionalpublic static void B(){System.out.println("测试");}
原因分析:
@Transactional的默认事务传播机制是REQUIRED ,并且B方法抛出异常的时候会标记rollback-only为true,然后A准备提交事务的时候发现rollback-only为true也会进行回滚并且把B抛出的异常信息给吞了。也就是我想要B的异常信息没给,只给了一个rollback-only信息给前端。
事务传播级别 | 说明 |
---|---|
PROPAGATION_REQUIRED | 如果当前没有事务,就创建一个事务,如果已经存在事务,就加入到这个事务。当前传播机制也是spring默认传播机制 |
PROPAGATION_REQUIRES_NEW | 新建事务,如果当前存在事务,就抛出异常。 |
PROPAGATION_SUPPORTS | 支持当前事务,如果当前没有事务,就以非事务方式执行。 |
PROPAGATION_NOT_SUPPORTED | 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 |
PROPAGATION_MANDATORY | 使用当前的事务,如果当前没有事务,就抛出异常 |
PROPAGATION_NEVER | 以非事务方式执行,如果当前存在事务,则抛出异常。 |
PROPAGATION_NESTED | 如果当前存在事务,则在嵌套的事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作 |
解决方案:
1、删除try-catch(不推荐)
这个没什么好说的,就是不进行try-catch,但是很多业务就是需要自己捕获异常,不让用户看到这个异常信息,继续维持服务器的运行。
2、修改事务传播级别
网上最为流传的解决方法就是根据业务设置不同的事务传播级别,将B方法的注解改为REQUIRES_NEW(A和B不需要同一个事务,把事务分开)或者NESTED(A和B同一个事务,但是B回滚的时候A不会回滚),即:
@Transactional(propagation = Propagation.REQUIRES_NEW)public void B(){System.out.println("测试");}
REQUIRED
- 假设在A⽅法存在⼀个当前事务,B⽅法的事务传播机制为REQUIRED,则B⽅法会合并到A⽅法的事务⾥执⾏。
- A、B任意⼀个⽅法异常(默认是RuntimeException和Error)都会导致A、B的操作被回滚。
- Spring事务管理器不会吞异常。
B异常后会抛给A,A如果没有catch这个异常,会继续向上抛。如果A catch住了,Spring事务管理器会替A向上抛⼀个
UnexpectedRollbackException。总之,⼀旦A、B回滚,A的调⽤⽅⼀定能收到⼀个异常感知到回滚。(问题所在)
REQUIRES_NEW
- 如果B发⽣异常,B事务⼀定回滚,B的异常随后会抛给A,如果A catch住了这个异常,A不会回滚,否则A也会回滚。
- 如果A发⽣异常,则只会回滚A,不会回滚B。
NESTED
- 如果B异常,B⼀定回滚,B的异常随后会抛给A,如果A catch住了这个异常,A不会回滚,否则A也会回滚。这种情况和REQUIRES_NEW⼀样。
- 如果A发⽣异常,则A、B都会回滚。
根据业务需求,后面两个传播级别是不符合我的需求的,因为会导致A或B的事务不回滚,第一个传播级别REQUIRED才符合但有问题,即第一个方法对我无效,大家可以先试试。
3、手动回滚(推荐)
这个是我在逛了无数的论坛和提问才发现的解决方案,在catch语句中增加:TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();语句,手动回滚,这样上层就无需去处理异常
示例代码如下:
@Transactionalpublic void A(){try{B();}catch(Exception e){TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();e.printStackTrace();}}@Transactionalpublic void B(){System.out.println("测试");}
参考文章:
事务传播级别(7种)
Spring事务嵌套引发的血案—Transaction rolled back because it has been marked as rollback-only
Spring嵌套事务异常Transaction rolled back because it has been marked as rollback-only相关推荐
- 【Spring】21、用spring目标对象处理Transaction rolled back because it has been marked as rollback-only...
在使用spring做事务管理时,很多人都会遇到这样一段异常: org.springframework.transaction.UnexpectedRollbackException: Transact ...
- 关于Spring嵌套事务异常问题
关于Spring嵌套事务异常问题 异常截图 异常信息: Transaction silently rolled back because it has been marked as rollback- ...
- Spring事务 Transaction rolled back because it has been marked as rollback-only
前言 使用Spring事务时,出现异常:org.springframework.transaction.UnexpectedRollbackException: Transaction rolled ...
- 关于spring事务传播行为引发的Transaction rolled back because it has been marked as rollback-only
偶尔博客闲逛发现有人讨论这个问题(我自己没有遇到过),翻了几个帖子没有几个讲清楚的,自己测试下吧 测试类: package com.web.service;import com.StudyApplic ...
- UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only
转载自:https://dongguabai.blog.csdn.net/article/details/114686998 PROPAGATION_REQUIRES_NEW:原有事务A新起事务B,事 ...
- Transaction rolled back because it has been marked as rollback-only
http://hsyd.iteye.com/blog/586772 错误信息: Transaction rolled back because it has been marked as rollba ...
- “Transaction rolled back because it has been marked as rollback-only”
spring的声明事务提供了强大功能,让我们把业务关注和非业务关注的东西又分离开了.好东西的使用,总是需要有代价的.使用声明事务的时候,一 个不小心经常会碰到"Transaction rol ...
- Transaction has been rolled back because it has been marked as rollback
框架采用的是spring管理声明式事务,这几天业务开发时遇到了点麻烦,记录下备忘. 场景:在Service类中使用子事务(saveponit)时,当子事务抛出异常后,此异常处理掉不继续往外抛,spri ...
- Transaction rolled back because it has been marked as rollback-only分析解决方法
Transaction rolled back because it has been marked as rollback-only分析解决方法 参考文章: (1)Transaction rolle ...
最新文章
- MPB:南农金巍等-​​​瘤胃甲烷菌的分离培养与保存
- c++98不支持set初始化列表
- Android PC投屏简单尝试—最终章1
- Elasticsearch嵌套查询
- HTML+CSS+JS实现美女照片3D立方体旋转特效
- Any-Proxy在线反向代理源码
- c语言程序设计课用电脑吗,C语言程序设计之简单计算器
- 《葵花宝典:WPF自学手册》三大网点书评集萃
- php怎么写脚本,PHP脚本来写Daemon程序_php
- RAID结构介绍以及RAID1、RAID0等各种模式的区别
- Unicode编码表
- pgadmin3连接mysql_postgresql – pgAdmin III:拒绝访问数据库
- 有了这套前端数据可视化框架,人人都能快速上手(赠100套前端可视化大屏模板)
- 【Python实用工具】查询本机IP地址
- 【优化系列】汇编优化技术(六):ARM架构64位(AARCH64)汇编优化及demo
- npm 实战精讲-曾亮-专题视频课程
- 20210514面试题自我分类及总结(一)
- 微观经济学论文选题怎么选?
- pandas 第十二期组队-pandas基础
- 数据代码分享|Python用NLP自然语言处理LSTM神经网络Twitter推特灾难文本数据、词云可视化与SVM,KNN,多层感知器,朴素贝叶斯,随机森林,GBDT对比