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 相关文章推荐
一个网页标题title的闪动提示效果实现思路
Mar 22 Javascript
JavaScript中如何通过arguments对象实现对象的重载
May 12 Javascript
JavaScript实现数组随机排序的方法
Jun 26 Javascript
纯javascript判断查询日期是否为有效日期
Aug 24 Javascript
三种方式实现瀑布流布局
Feb 10 Javascript
Vue.js 动态为img的src赋值方法
Mar 14 Javascript
小程序实现左右来回滚动字幕效果
Dec 28 Javascript
详解Vue.js v-for不支持IE9的解决方法
Dec 29 Javascript
vue路由跳转传递参数的方式总结
May 10 Javascript
vue实现匀速轮播效果
Jun 29 Javascript
解决nuxt 自定义全局方法,全局属性,全局变量的问题
Nov 05 Javascript
你不知道的SpringBoot与Vue部署解决方案
Nov 09 Javascript
使用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下载xls文件(自己动手写的)
2014/04/18 PHP
PHP代码重构方法漫谈
2018/04/17 PHP
PHP实现断点续传乱序合并文件的方法
2018/09/06 PHP
JQery 渐变图片导航效果代码 漂亮
2010/01/01 Javascript
jQuery each()小议
2010/03/18 Javascript
Jquery css函数用法(判断标签是否拥有某属性)
2011/05/28 Javascript
js 操作select和option常用代码整理
2012/12/13 Javascript
解析JavaScript中instanceof对于不同的构造器或许都返回true
2013/12/03 Javascript
jQuery简单实现两级下拉菜单效果代码
2015/09/15 Javascript
两款JS脚本判断手机浏览器类型跳转WAP手机网站
2015/10/16 Javascript
JS实现把鼠标放到链接上出现滚动文字的方法
2016/04/06 Javascript
JavaScript中最容易混淆的作用域、提升、闭包知识详解(推荐)
2016/09/05 Javascript
详解AngularJS跨页面传值(ui-router)
2017/08/23 Javascript
VsCode插件整理(小结)
2017/09/14 Javascript
微信小程序实现留言功能
2018/10/31 Javascript
vue实现父子组件之间的通信以及兄弟组件的通信功能示例
2019/01/29 Javascript
解决layui表格的表头不滚动的问题
2019/09/04 Javascript
javascript设计模式 ? 外观模式原理与用法实例分析
2020/04/15 Javascript
使用 UniApp 实现小程序的微信登录功能
2020/06/09 Javascript
[01:19:35]DOTA2上海特级锦标赛主赛事日 - 3 败者组第三轮#2Fnatic VS OG第二局
2016/03/05 DOTA
Python import用法以及与from...import的区别
2015/05/28 Python
python与php实现分割文件代码
2017/03/06 Python
使用Python写一个贪吃蛇游戏实例代码
2017/08/21 Python
flask中使用蓝图将路由分开写在不同文件实例解析
2018/01/19 Python
Python增强赋值和共享引用注意事项小结
2019/05/28 Python
解决keras模型保存h5文件提示无此目录问题
2020/07/01 Python
matplotlib图例legend语法及设置的方法
2020/07/28 Python
Pycharm 解决自动格式化冲突的设置操作
2021/01/15 Python
新西兰床上用品和家居用品购物网站:Adairs
2018/04/27 全球购物
加拿大的标志性百货公司:Hudson’s Bay(哈得逊湾)
2019/09/03 全球购物
贪睡宠物用品:Snoozer Pet Products
2020/02/04 全球购物
汽车工程专业应届生求职信
2013/10/19 职场文书
培训主管的职业生涯规划
2014/03/06 职场文书
学校国庆节活动总结
2015/03/23 职场文书
沂蒙六姐妹观后感
2015/06/08 职场文书
Nginx报错104:Connection reset by peer问题的解决及分析
2022/07/23 Servers