这里有新鲜出炉的 Java 设计模式,程序狗速度看过来!
java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的 Java 程序设计语言和 Java 平台(即 JavaEE(j2ee), JavaME(j2me), JavaSE(j2se))的总称。
这篇文章主要介绍了 java Spring 事务回滚的相关资料, 需要的朋友可以参考下
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)。
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,可以看下面的源码
那么现在有两个情况
情况 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()是会回滚的
- }
- }
感谢您的阅读!谢谢!
来源: http://www.phperz.com/article/17/0713/331131.html