本人最近在使用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异常。

针对上述事务无法提交的解决办法,本人现在总结了两种处理方法,有路过的看到过的,要是还有什么较好的解决方法,不妨给本人留言,大家共同探讨,一起进步吧!言归正传,本人的总结出的这两种解决方法描述如下:

  1. serviceB.methodB不声明为事务代理。 但是很多时候serviceB.methodB也被其他地方使用,并且是需要事务管理的。这时候可以重写一个方法。但是要注意这个方法中数据的一致性。

  2. 和1一样也是重写一个serviceB.methodB方法,但在里面不抛出异常,而是将异常转化为一个布尔值并返回,这个返回的布尔值相当于一个标记methodB是否在执行过程中出现异常的状态值。methodA可以根据这个返回的状态值判断后续代码是否有必要继续执行。这样,也可以避免上述异常的产生。

注:http://blog.csdn.net/nmgrd/article/details/51883405

本人遇到的spring事务之UnexpectedRollbackException异常解决笔记的更多相关文章

  1. 踩坑系列《六》Spring增加事务处理遇到异常解决办法

    当在对数据进行增删改操作时,需要用到事务的处理,所以在业务层中加入@Transactional注解,但是在执行业务操作的前面遇到异常,因此对异常进行抛出,但是数据又诡异地成功保存到数据库了. 解决方法 ...

  2. Spring事务回滚和异常类

    1.异常的一些基本知识 异常的架构 异常的继承结构:Throwable为基类,Error和Exception继承Throwable.Error和RuntimeException及其子类成为未检查异常( ...

  3. java异常与spring事务关系的知识点查漏补缺

    一.基础概念 java的异常结构图 从图中可知 Throwable是所有异常的根,java.lang.Throwable Error是错误,java.lang.Error Exception是异常,j ...

  4. spring 事务传播

    1.spring实现对事务的控制,使用的是代理的技术.通过生成的代理类来捕捉被代理类(也就是我们编写的类)的异常,决定事务的提交或回滚.从某一角度来说,spring事务是基于异常实现的.对于实现了接口 ...

  5. Spring事务超时、回滚的相关说明

    事务超时: @Transactional(timeout = 60) 如果用这个注解描述一个方法的话,线程已经跑到方法里面,如果已经过去60秒了还没跑完这个方法并且线程在这个方法中的后面还有涉及到对数 ...

  6. Spring事务管理之几种方式实现事务(转)

    一:事务认识 大家所了解的事务Transaction,它是一些列严密操作动作,要么都操作完成,要么都回滚撤销.Spring事务管理基于底层数据库本身的事务处理机制.数据库事务的基础,是掌握Spring ...

  7. 面试突击87:说一下 Spring 事务传播机制?

    Spring 事务传播机制是指,包含多个事务的方法在相互调用时,事务是如何在这些方法间传播的. 既然是"事务传播",所以事务的数量应该在两个或两个以上,Spring 事务传播机制的 ...

  8. Spring 事务管理原理探究

    此处先粘贴出Spring事务需要的配置内容: 1.Spring事务管理器的配置文件: 2.一个普通的JPA框架(此处是mybatis)的配置文件: <bean id="sqlSessi ...

  9. Spring事务异常rollback-only

    转自:https://blog.csdn.net/sgls652709/article/details/49472719 前言 在利用单元测试验证spring事务传播机制的时候出现了下面的异常: Tr ...

随机推荐

  1. C# 生成四位数字字母混合验证码

    private static void Rand() { var arr = new List<string>(); ; i < ; i++) { arr.Add(i.ToStrin ...

  2. 使用linuxbridge + vlan网络模式

    #openstack pike 使用 linuxbridge + vlan openstack pike 集群高可用  安装部署 汇总 http://www.cnblogs.com/elvi/p/76 ...

  3. Android中的Handler及它所引出的Looper、MessageQueue、Message

    0.引入 0.1.线程间通信的目的 首先,线程间通信要交流些什么呢? 解答这个问题要从为什么要有多线程开始,需要多线程的原因大概有这些 最早也最基本:有的任务需要大量的时间,但其实并不占用计算资源,比 ...

  4. Keras-在预训练好网络模型上进行fine-tune

    在深度学习的学习过程中,可能会用到一些已经训练好的模型,比如Alex Net,google Net,VGG,Resnet等,那我们怎样对这些训练好的模型进行fine-tune来提高准确率呢? 参考文章 ...

  5. 第1章 1.7计算机网络概述--理解OSI参考模型分层思想

    OSI七层模型,知识参考理论. 分层标准的好处: 1.不同的硬件生产商生产的硬件产品,连通后就可以用了,有助于互联网发展. 2.分层,分成不同的模块,某一层的变化,不会影响其他层.如:IPv4改为IP ...

  6. Mysql5.7.10新加用户

    INSERT INTO mysql.user(HOST,USER,authentication_string,ssl_cipher,x509_issuer,x509_subject,select_pr ...

  7. 关于c语言struct和typedef

    C++中使用: struct test{    int x, y;};就可以定义一个名为 test的结构体,但C中很可能编译通不过.C语言并不支持在struct后使用标示符定义结构体的名字,test将 ...

  8. Java用数据结构解决实现问题之数学问题

    有趣的整数: 完数:如果一个数字恰好等于他的因子之和,就叫做完数,需求是求出10000以内的所有的完数. 解法:1.用n去除以1-n之间的所有的整数,将能整除的被除数保存到一个数组中,作为n的一个因子 ...

  9. python tesseract-ocr 安装包下载地址

    https://github.com/UB-Mannheim/tesseract/wiki 如图:可以选合适的版本进行下载

  10. 【运维技术】Zookeeper单机以及集群搭建教程

    Zookeeper单机以及集群搭建教程 单机搭建 单机安装以及启动 安装zookeeper的前提是必须有java环境 # 选择目录进行下载安装 cd /app # 下载zk,可以去官方网站下载,自己上 ...