spring管理事务回滚

spring 事务回滚

1、遇到的问题

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

?


1

2

3

4

5

6

7

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、实例

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

?


1

2

3

4

5

6

7

<!-- 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了,那么方法中如果自己捕获了异常,事务是不会回滚的,如果没有自己捕获异常则事务会回滚,如下例
比如配置文件里有这么条记录

?


1

2

3

4

5

6

7

8

9

10

<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:如果没有在程序中手动捕获异常

?


1

2

3

4

5

@Transactional(rollbackOn = { Exception.class })

public void test() throws Exception {

   doDbStuff1();

   doDbStuff2();//假如这个操作数据库的方法会抛出异常,现在方法doDbStuff1()对数据库的操作  会回滚。

}

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

?


1

2

3

4

5

6

7

8

9

@Transactional(rollbackOn = { Exception.class })

public void test() {

   try {

    doDbStuff1();

    doDbStuff2();//假如这个操作数据库的方法会抛出异常,现在方法doDbStuff1()对数据库的操作 不会回滚。

   } catch (Exception e) {

      e.printStackTrace();  

   }

}

  现在如果我们需要手动捕获异常,并且也希望抛异常的时候能回滚肿么办呢?
  下面这样写就好了,手动回滚事务:

?


1

2

3

4

5

6

7

8

9

10

@Transactional(rollbackOn = { Exception.class })

public void test() {

   try {

    doDbStuff1();

    doDbStuff2();

   } catch (Exception e) {

     e.printStackTrace();  

     TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();//就是这一句了,加上之后,如果doDbStuff2()抛了异常,                                            //doDbStuff1()是会回滚的

   }

}

感谢您的阅读!谢谢!

时间: 2024-10-11 20:45:46

spring管理事务回滚的相关文章

Spring @Transactional ——事务回滚

工作原理运行配置@Transactional注解的测试类的时候,具体会发生如下步骤1)事务开始时,通过AOP机制,生成一个代理connection对象,并将其放入DataSource实例的某个与DataSourceTransactionManager相关的某处容器中.在接下来的整个事务中,客户代码都应该使用该connection连接数据库,执行所有数据库命令[不使用该connection连接数据库执行的数据库命令,在本事务回滚的时候得不到回滚]2)事务结束时,回滚在第1步骤中得到的代理conne

spring之事务回滚技巧

1.遇到的问题 当我们一个方法里面有多个数据库保存操作的时候,中间的数据库操作发生的错误.伪代码如下: public method() {    Dao1.save(Person1);    Dao1.save(Person2);    Dao1.save(Person2);    //假如这句发生了错误,前面的两个对象会被保存到数据库中    Dao1.save(Person2);} 期待的情况:发生错误之前的所有数据库保存操作都回滚,即不保存 正常情况:前面的数据库操作会被执行,而发生数据库

spring的事务回滚

@Transactional(rollbackFor = { Exception.class }) 需要把异常抛出到带有@Transactional(rollbackFor = { Exception.class })  这个注释的函数外面,回滚才能生效. 出现错误: org.springframework.orm.hibernate3.HibernateSystemException: identifier of an instance of com.cqut.entity.outintask

ssh事务回滚,纪念这几个月困扰已久的心酸

以前的事务采用的是JTA,xml注入的方式.本人就着开发要优雅合理利用轮子的态度,一直不满意JTA式的申明和切入方式. spring的注解方式多优雅,可是万恶的直到项目快要上线时终于找到了注解式不能回滚的缘由. Spring的事务回滚,当且仅当捕获到RuntimeException类型异常时,才会回滚,对普通Exception异常无效. 满满一把心酸泪,,, 原理:代码贴上: 配置可参考如下:http://blog.csdn.net/greensurfer/article/details/752

用Spring TestContext 做带事务回滚的JUnit测试

JUnit单元测试框架很常用 但可能会破坏数据库现场 以及大量的硬编码出现(applicationContext.getBean("")); 今天哥们给新手介绍一下 Spring Test这个Spring自带的jar包中的一些注解 实现单元测试+事务回滚+注解依赖注入 网上的相关教程不多 我的意思是有用的不多 基本都是类似api文档那种 给你罗列一大堆注解和类 告诉你他们的作用 你看完了也不知道该从哪里入手 我自己琢磨了几天(哥们天赋不是很高) 写了一个测试类 测试成功 给大家分享一下

(转)spring异常抛出触发事务回滚策略

背景:在面试时候问到事务方法在调用过程中出现异常,是否会传递的问题,平时接触的比较少,有些懵逼. spring异常抛出触发事务回滚策略 Spring.EJB的声明式事务默认情况下都是在抛出unchecked exception后才会触发事务的回滚 测试用业务逻辑方法: /** * 如果在spring事务配置中不为切入点(如这里的切入点可以定义成test*)配置事务在什么情况下回滚(格式:-引起回滚的异常类型) * 则spring默认只会在service方法抛出unchecked exceptio

spring事务回滚的一些个人总结

1.  spring的事务边界是在调用业务方法之前开始的,业务方法执行完毕之后来执行commit or rollback(取决于是否抛出runtime异常). 2.  如果抛出runtime exception 并在你的业务方法中没有try-catch到的话,事务会回滚,所以一般不在业务层try-catch. 3. 一般不需要在业务方法中catch异常,一般在调用该service的action中catch,然后将结果导到出错页面,如果非要try-catch,在做完你想做的工作后(比如关闭文件等)

MySQL(22):事务管理之 事务回滚

1. 在操作事务的时候,如果发现当前事务操作是不合理的,此时只要还没有提交事务,就可以通过回滚取消当前事务,接下来就针对事务的回滚进行详细讲解. 2. 为了演示回滚操作,在上一个笔记案例基础之上,此时a账户有1000元,b账户也有1000元,开启一个事务,通过update语句将a账户的100元转给b账户,具体语句,如下: start transaction; update account set money=money-100 where name='a'; update account set

配置Spring JDBC的事务回滚失效

今天配置Mysql DBCP连接池事务回滚失效,竟然浪费了我一下午的时间去调研,问了好多人也都没发现,最后还得靠自己,总结问题如下: 1.Mysql数据库用的是MyISAM表结构而非InnerDB(浪费了两个小时) 2.网上说的默认情况下,一个有事务方法, 遇到RuntiomeException 时会回滚 . 遇到 受检查的异常 是不会回滚 的. 要想所有异常都回滚,要加上 @Transactional( rollbackFor={Exception.class,其它异常}) . 3.配置DBC