本人遇到的spring事务之UnexpectedRollbackException异常解决笔记
本人最近在使用spring事务管理的过程中遇到如下异常,导致服务端抛出500给前端,让搞前端的哥们抱怨我心里着实不爽,前前后后折腾了近半个小时才得于解决,今天就做个笔记,以免日后又犯这个错误。好了,错误是这样的:
org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only
后来才发现,我这个问题在ssh或者ssm之类的框架下其实是具有一定的普遍性的。上述异常一般都会出现在下述java伪代码描述的场景中:
在ssh或者ssm等框架集成的项目中,通常service层的事务是由spring代理的。service层的方法发生或抛出异常,则事务会回滚,导致无法提交。通常,我们的项目都会设有全局的异常处理机制,一旦发生异常,会有全局的异常处理机制进行统一处理,所以一般不需要在代码中主动捕获异常。
然而,某些特殊的场景中,比如下面的业务层serviceA具有方法methodA,methodA会调用另一个业务层serviceB的方法methodB。在methodA的实际执行过程中,假如methodB有可能抛出异常,但在methodB无论执行是否正常都不能影响methodA的执行的情况下,通常需要methodA主动捕获这个异常。在methodA主动捕获这个异常的情况下,只要methodA的其他代码不抛出异常,则methodA是不会抛出任何异常的。既然methodA不会抛出异常,道理上讲作用于methodA上的事务是应该可以正常提交的呀,对不对?然而事实上,一旦methodB抛出异常,不管methodA的其他代码是否正确执行,整个事务是无法提交的(说这句话的前提是methodA和methodB上都具有事务,并且都由spring进行统一的事务管理)。
serviceA.methodA()
{
doSomethingA(); try {
serviceB.methodB{}; //这里面有异常标记为回滚, doSetRollbackOnly(status);
}
catch {
//捕获异常转到commit时,由于已经标记为要回滚, 回滚并抛出新异常
} doSomethingB(); }
出现上述异常是因为自己之前没有很好的理解spring事务的机制。 上述的methodA被调用执行时,有两个点是被spring事务代理的。也即serviceA.methodA()和serviceB.methodB(),这两个方法中只要有异常事件将回滚。 上述场景中存在事务嵌套,如果methodA中有异常出现事务会直接回滚,但methodB中有异常只是标记状态为需要回滚,最终在methodA中回滚。 上述场景中methodB有异常事务被标记为回滚,可是被methodA捕获了,也就不回滚了,一直执行到最后commit。在commit时spring会判断回滚标志,若检测到存在回滚标记, 则回滚事务并抛出UnexpectedRollbackException异常。
针对上述事务无法提交的解决办法,本人现在总结了两种处理方法,有路过的看到过的,要是还有什么较好的解决方法,不妨给本人留言,大家共同探讨,一起进步吧!言归正传,本人的总结出的这两种解决方法描述如下:
serviceB.methodB不声明为事务代理。 但是很多时候serviceB.methodB也被其他地方使用,并且是需要事务管理的。这时候可以重写一个方法。但是要注意这个方法中数据的一致性。
和1一样也是重写一个serviceB.methodB方法,但在里面不抛出异常,而是将异常转化为一个布尔值并返回,这个返回的布尔值相当于一个标记methodB是否在执行过程中出现异常的状态值。methodA可以根据这个返回的状态值判断后续代码是否有必要继续执行。这样,也可以避免上述异常的产生。
注:http://blog.csdn.net/nmgrd/article/details/51883405
本人遇到的spring事务之UnexpectedRollbackException异常解决笔记的更多相关文章
- 踩坑系列《六》Spring增加事务处理遇到异常解决办法
当在对数据进行增删改操作时,需要用到事务的处理,所以在业务层中加入@Transactional注解,但是在执行业务操作的前面遇到异常,因此对异常进行抛出,但是数据又诡异地成功保存到数据库了. 解决方法 ...
- Spring事务回滚和异常类
1.异常的一些基本知识 异常的架构 异常的继承结构:Throwable为基类,Error和Exception继承Throwable.Error和RuntimeException及其子类成为未检查异常( ...
- java异常与spring事务关系的知识点查漏补缺
一.基础概念 java的异常结构图 从图中可知 Throwable是所有异常的根,java.lang.Throwable Error是错误,java.lang.Error Exception是异常,j ...
- spring 事务传播
1.spring实现对事务的控制,使用的是代理的技术.通过生成的代理类来捕捉被代理类(也就是我们编写的类)的异常,决定事务的提交或回滚.从某一角度来说,spring事务是基于异常实现的.对于实现了接口 ...
- Spring事务超时、回滚的相关说明
事务超时: @Transactional(timeout = 60) 如果用这个注解描述一个方法的话,线程已经跑到方法里面,如果已经过去60秒了还没跑完这个方法并且线程在这个方法中的后面还有涉及到对数 ...
- Spring事务管理之几种方式实现事务(转)
一:事务认识 大家所了解的事务Transaction,它是一些列严密操作动作,要么都操作完成,要么都回滚撤销.Spring事务管理基于底层数据库本身的事务处理机制.数据库事务的基础,是掌握Spring ...
- 面试突击87:说一下 Spring 事务传播机制?
Spring 事务传播机制是指,包含多个事务的方法在相互调用时,事务是如何在这些方法间传播的. 既然是"事务传播",所以事务的数量应该在两个或两个以上,Spring 事务传播机制的 ...
- Spring 事务管理原理探究
此处先粘贴出Spring事务需要的配置内容: 1.Spring事务管理器的配置文件: 2.一个普通的JPA框架(此处是mybatis)的配置文件: <bean id="sqlSessi ...
- Spring事务异常rollback-only
转自:https://blog.csdn.net/sgls652709/article/details/49472719 前言 在利用单元测试验证spring事务传播机制的时候出现了下面的异常: Tr ...
随机推荐
- 《挑战程序设计竞赛》2.5 最小生成树 POJ3723 3169 1258 2377 2395 AOJ2224(1)
POJ3723 http://poj.org/problem?id=3723 题意 windy要组建一支军队,召集了N个女孩和M个男孩,每个人要付10000RMB,但是如果一个女孩和一个男孩有关系d的 ...
- rk3188 双屏异显分析
首先是android层: PhoneWindow.java 中加入了GestureDetector成员, 来实现全局滑屏手势监听 onFling方法中,调用了mDecor.getRootWindo ...
- docker 数据管理数据卷
1,数据卷 数据卷是一个可供容器使用特殊目录,他将主机操作系统目录直接映射容器 1,在容器内创建一个数据卷 在使用docker run命令的时候,使用-v标记就可以创建一个数据卷,多次重复使用-v可以 ...
- 纯css3加载动画
<!DOCTYPE html><html> <head> <meta charset="utf-8"> <meta name= ...
- gcd倒计时
@interface ViewController () { dispatch_source_t _timer; } @property (weak, nonatomic) IBOutlet UILa ...
- SqlServer PIVOT函数快速实现行转列,UNPIVOT实现列转行(转)
我们在写Sql语句的时候没经常会遇到将查询结果行转列,列转行的需求,拼接sql字符串,然后使用sp_executesql执行sql字符串是比较常规的一种做法.但是这样做实现起来非常复杂,而在SqlSe ...
- 鸟哥linux私房菜学习笔记,U盘安装centos5.3不能正常进入图形界面的问题
前面说过自己成功引导了centos系统,现在进入启动界面,首次进入会进行相关设置,按照步骤一步一步完成,取消完光盘安装,点击下一步,就进入下面这个界面,没有登录框...没错!怎么蓝屏了,这可是linu ...
- 【pycharm】pycharm中设置virtualenv的虚拟环境为开发环境
pycharm中设置virtualenv的虚拟环境 因为在pycharm写代码比较方便 但是有时候virtualenv安装的环境在pycharm中会有红色波浪线报语法错误.作为一个强迫症,这怎么能忍, ...
- D题:数学题(贪心+二分)
原题大意:原题链接 题解链接 给定两个集合元素,求出两集合间任意两元素相除后得到的新集合中的第k大值 #include<cstdio> #include<algorithm> ...
- try with resources简洁的异常捕获机制
通过前篇的<Java文件IO流的操作总结>,我们知道了基本输入输出流的使用方式,但是每次都需要在finally处关闭流资源,这样操作起来既啰嗦又麻烦,有没有更简洁的方式呢?本篇就来讲解jd ...