本人遇到的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 ...
随机推荐
- linux加载硬盘过程
查看系统可用磁盘大小: [root@i-mbyar7df ~]# df -h Filesystem Size Used Avail Use% Mounted on /dev/sda1 ...
- nginx:正向代理和反向代理
一.正向代理 原理:正向代理是一个位于客户端和目标服务器之间的代理服务器(中间服务器).为了从目标服务器取得内容,客户端向代理服务器发送一个请求,并且指定目标服务器,之后代理向目标服务器转交并且将获得 ...
- DNS中A记录和CNAME记录的区别(转)
A记录是域名到ip的映射,即为ip起别名:CNAME是域名别名到域名的映射,即为域名起别名. 还有一个常用的记录是MX记录,它是与邮件相关的,MX记录记录了发送电子邮件时域名对应的服务器地址. 原文: ...
- conda
Conda是什么? Conda 是Anaconda下用于包管理和环境管理的命令行工具, Conda下一切都是包,包括Python和conda自己 Conda ≍ pip(包管理) + vitualen ...
- tooltip提示文字
<p class="tooltip-demo">Tigh <a title="Default tooltip" rel="toolt ...
- 通过html<map>标签给图片加链接
前面我们有谈到了通过图片定位给一张图片添加多个链接,现在用另外一种方法来实现,用html<map>标签给图片加链接 <img src="/images/hlj.jpg&qu ...
- synchronized修饰的方法之间相互调用
1:synchronized修饰的方法之间相互调用,执行结果为There hello ..因为两个方法(main,hello)的synchronized形成了互斥锁. 所以当main方法执行完之后 ...
- c/c++值传递和引用传递
今天看数据结构的时候,因为是c语言版的,刚开始学的时候就对指针搞的焦头烂额,今天,发现参数传递的时候,&符号也莫名其妙,搜了一篇好文,转载下来. 一. 函数参数传递机制的基本理论 函数参数传递 ...
- HashSet、HashMap、Hashtable、TreeMap循环、区别
HashSet 循环 //可以为null HashSet<Object> hashSet =new HashSet<Object>(); hashSet.add(1); has ...
- Bootstrap fileinput v1.0(ssm版)
前言bootstrap fileinput是一个很好的文件上传插件.但是官方不出api,这就尴尬了.百度一下,每个人写法都不相同,好多代码本身都是错的.我修改后才能跑起来.综上所述:所以今天我摸索了一 ...