Java  Spring 事务回滚详解


Posted in Javascript onOctober 17, 2016

spring 事务回滚

1、遇到的问题

当我们一个方法里面有多个数据库保存操作的时候,中间的数据库操作发生的错误。伪代码如下:

public method() {
  Dao1.save(Person1);
  Dao1.save(Person2);

  Dao1.save(Person2);//假如这句发生了错误,前面的两个对象会被保存到数据库中
  Dao1.save(Person2);
}

期待的情况:发生错误之前的所有数据库保存操作都回滚,即不保存

正常情况:前面的数据库操作会被执行,而发生数据库操作错误开始及之后的所有的数据保存操作都将失败。这样子应该都不是我们要的结果吧。

当遇到这种情况,我们就可以使用Spring的事务解决这个问题。

2、异常的一些基本知识

1) 异常的架构

异常的继承结构:Throwable为基类,Error和Exception继承Throwable,RuntimeException和IOException等继承Exception。Error和RuntimeException及其子类成为未检查异常(unchecked),其它异常成为已检查异常(checked)。

Java  Spring 事务回滚详解

2)Error异常

Error表示程序在运行期间出现了十分严重、不可恢复的错误,在这种情况下应用程序只能中止运行,例如JAVA 虚拟机出现错误。Error是一种unchecked Exception,编译器不会检查Error是否被处理,在程序中不用捕获Error类型的异常。一般情况下,在程序中也不应该抛出Error类型的异常。

3)RuntimeException异常

Exception异常包括RuntimeException异常和其他非RuntimeException的异常。

RuntimeException 是一种Unchecked Exception,即表示编译器不会检查程序是否对RuntimeException作了处理,在程序中不必捕获RuntimException类型的异常,也不必在方法体声明抛出 RuntimeException类。RuntimeException发生的时候,表示程序中出现了编程错误,所以应该找出错误修改程序,而不是去捕获RuntimeException。

4)Checked Exception异常

Checked Exception异常,这也是在编程中使用最多的Exception,所有继承自Exception并且不是RuntimeException的异常都是checked Exception,上图中的IOException和ClassNotFoundException。JAVA 语言规定必须对checked Exception作处理,编译器会对此作检查,要么在方法体中声明抛出checked Exception,要么使用catch语句捕获checked Exception进行处理,不然不能通过编译。

3、实例

这里使用的事务配置如下:

<!-- Jpa 事务配置 -->
  <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory"/>
  </bean>
  
  <!-- 开启注解事务 -->
  <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />

在spring的配置文件中,如果数据源的defaultAutoCommit设置为True了,那么方法中如果自己捕获了异常,事务是不会回滚的,如果没有自己捕获异常则事务会回滚,如下例
比如配置文件里有这么条记录

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> 

<property name="xxx" value="xxx"/> 

<property name="xxx" value="xxx"/>

 ....
 <property name="defaultAutoCommit" value="true" /> 

</bean>

可能你会发现你并没有配置这个参数,是不是他就不会自动提交呢?答案是不是的,我这里是使用了com.alibaba.druid.pool.DruidDataSource作为数据库连接池,默认的defaultAutoCommit就是true,可以看下面的源码

 Java  Spring 事务回滚详解

那么现在有两个情况

情况1:如果没有在程序中手动捕获异常

@Transactional(rollbackOn = { Exception.class }) 
public void test() throws Exception { 
   doDbStuff1(); 
   doDbStuff2();//假如这个操作数据库的方法会抛出异常,现在方法doDbStuff1()对数据库的操作  会回滚。 
}

情况2:如果在程序中自己捕获了异常

@Transactional(rollbackOn = { Exception.class }) 
public void test() { 
   try { 
    doDbStuff1(); 
    doDbStuff2();//假如这个操作数据库的方法会抛出异常,现在方法doDbStuff1()对数据库的操作 不会回滚。 
   } catch (Exception e) { 
      e.printStackTrace();   
   } 
}

现在如果我们需要手动捕获异常,并且也希望抛异常的时候能回滚肿么办呢?

下面这样写就好了,手动回滚事务:

@Transactional(rollbackOn = { Exception.class }) 
public void test() { 
   try { 
    doDbStuff1(); 
    doDbStuff2(); 
   } catch (Exception e) { 
     e.printStackTrace();   
     TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();//就是这一句了,加上之后,如果doDbStuff2()抛了异常,                                            //doDbStuff1()是会回滚的 
   } 
}

   感谢您的阅读!谢谢!

Javascript 相关文章推荐
js实现权限树的更新权限时的全选全消功能
Feb 17 Javascript
javascript 基础篇4 window对象,DOM
Mar 14 Javascript
对js关键字命名的疑问介绍
Apr 25 Javascript
JavaScript中检查对象property的存在性方法介绍
Dec 30 Javascript
基于jQuery实现select下拉选择可输入附源码下载
Feb 03 Javascript
关于JavaScript和jQuery的类型判断详解
Oct 08 Javascript
jQuery html表格排序插件tablesorter使用方法详解
Feb 10 Javascript
Angular中使用$watch监听object属性值的变化(详解)
Apr 24 Javascript
vue this.reload 方法 配置
Sep 12 Javascript
jsonp跨域获取百度联想词的方法分析
May 13 Javascript
浅谈JS的原型和原型链
Jun 04 Javascript
vue打包时去掉所有的console.log
Apr 10 Vue.js
使用jquery.qrcode.js生成二维码插件
Oct 17 #Javascript
js浏览器html5表单验证
Oct 17 #Javascript
使用开源工具制作网页验证码的方法
Oct 17 #Javascript
jQuery 实现ajax传入参数含有特殊字符的方法总结
Oct 17 #Javascript
JavaScript中的ajax功能的概念和示例详解
Oct 17 #Javascript
JQuery中解决重复动画的方法
Oct 17 #Javascript
bootstrap读书笔记之CSS组件(上)
Oct 17 #Javascript
You might like
?算你??的 PHP 程式大小
2006/12/06 PHP
php获取指定日期之间的各个周和月的起止时间
2014/11/24 PHP
php通过curl添加cookie伪造登陆抓取数据的方法
2016/04/02 PHP
PHP反射机制原理与用法详解
2017/02/15 PHP
PHP实现一个轻量级容器的方法
2019/01/28 PHP
php实现QQ小程序发送模板消息功能
2019/09/18 PHP
Laravel 5.4前后台分离,通过不同的二级域名访问方法
2019/10/13 PHP
ajax 文件上传应用简单实现
2009/03/03 Javascript
JavaScript 闭包深入理解(closure)
2009/05/27 Javascript
Jquery实现点击按钮,连续地向textarea中添加值的实例代码
2014/03/08 Javascript
jQuery实现数秒后自动提交form的方法
2015/03/05 Javascript
PHP+jQuery实现随意拖动层并即时保存拖动位置
2015/04/30 Javascript
Jquery代码实现图片轮播效果(一)
2015/08/12 Javascript
jquery实现可点击伸缩与展开的菜单效果代码
2015/08/31 Javascript
js css3实现图片拖拽效果
2017/03/04 Javascript
AngularJS日程表案例详解
2017/08/15 Javascript
JS去掉字符串中所有的逗号
2017/10/18 Javascript
p5.js 毕达哥拉斯树的实现代码
2018/03/23 Javascript
微信小程序实现分享朋友圈的图片功能示例
2019/01/18 Javascript
弱类型语言javascript开发中的一些坑实例小结【变量、函数、数组、对象、作用域等】
2019/08/07 Javascript
浅谈JavaScript中this的指向更改
2020/07/28 Javascript
Python中的True,False条件判断实例分析
2015/01/12 Python
Python使用修饰器执行函数的参数检查功能示例
2017/09/26 Python
Python Web程序部署到Ubuntu服务器上的方法
2018/02/22 Python
对pandas中to_dict的用法详解
2018/06/05 Python
Django 自动生成api接口文档教程
2019/11/19 Python
详解Flask前后端分离项目案例
2020/07/24 Python
Python从MySQL数据库中面抽取试题,生成试卷
2021/01/14 Python
html5 兼容IE6结构的实现代码
2012/05/14 HTML / CSS
美丽的珠宝配饰:SmallThings
2019/09/04 全球购物
什么是SQL Server的确定性函数和不确定性函数
2016/08/04 面试题
危爆物品安全大检查大整治工作方案
2014/05/03 职场文书
公司离职证明范本(5篇)
2014/09/17 职场文书
2014旅游局党组书记党建工作汇报材料
2014/11/02 职场文书
多属性、多分类MySQL模式设计
2021/04/05 MySQL
Spring中bean的生命周期之getSingleton方法
2021/06/30 Java/Android