zoukankan      html  css  js  c++  java
  • Spring-Java事物回滚失效处理

    spring-Java事物回滚失效处理最近在做项目中,无意间发现有个类在抛事物回滚操作,数据也正常的插入到数据库当中了,于是仔细查看看一下具体原因。

    一切还是要从Java的检查型异常和非检查型异常说起。

    那么什么是检查型异常什么又是非检查型异常呢?
     最简单的判断点有两个:
        1.继承自RuntimeException或Error的是非检查型异常,而继承自Exception的则是检查型异常(当然,RuntimeException本身也是Exception的子类)。
        2.对非检查型类异常可以不用捕获,而检查型异常则必须用try……catch语句块进行处理或者把异常交给上级方法处理,总之就是必须写代码处理它。

    Java 的异常结构如下图。其中直接继承Exception的异常,必须捕获,属于检查型异常。


    再回过来看我的代码:

    1、方法名前面有

    1. @Transactional  

    2、Spring的配置文件applicationContext-XXX.xml当中也有Spring事物的相关配置

    1. <bean id="transactionManager"  
    2.     class="org.springframework.jdbc.datasource.DataSourceTransactionManager">  
    3.     <property name="dataSource" ref="dataSource" />  
    4.     <property name="rollbackOnCommitFailure" value="true"></property>  
    5. </bean>  


    但是为什么在Service层方法调用的时候,try……catch抛Exception异常已经提交的事物却没有回滚?

    查看相关spring的文档后发现,原来spring声明式事务管理默认对非检查型异常和运行时异常进行事务回滚,而对检查型异常则不进行回滚操作。

    代码中try……catch抛出的Exception异常,属于检查型异常,Spring的框架默认是不会进行回滚的。

    在编程中对非检查型类异常可以不用捕获,而检查型异常则必须用try语句块进行处理或者把异常交给上级方法处理总之就是必须写代码处理它。

    所以必须在service捕获异常,然后再次手动 throw 一个非检查型异常,这样事务方才起效。例如:

    1. try{  
    2.     …………  
    3. catch (Exception e) {  
    4.     …………  
    5.     throw new BusinessException(e.getMessage());  
    6. }  

    或者

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

    当然我们还有更简便的方法来解决这个问题,那就是通过注解参数改变默认的回滚方式 。

    在@Transaction注解中定义了noRollbackFor和RollbackFor来指定某种异常是否回滚。

    使用例:

        @Transaction(noRollbackFor=RuntimeException.class)

        @Transaction(RollbackFor=Exception.class)

    所以上述的问题可以直接将@Transaction添加回滚参数@Transaction(RollbackFor=Exception.class) ,这样就改变了默认的事务处理方式。


    启示 :

    这就要求我们在自定义异常的时候,让自定义的异常继承自RuntimeException,这样抛出的时候才会被Spring默认的事务处理准确处理。
  • 相关阅读:
    不允许使用邮箱名称。 服务器响应为: Mail from must equal authorized user
    SQL SERVER MD5
    c#转VB.NET
    SQL Sqlserver查询的安全性和性能的优化(转载)
    SQL Server 开发人员需要避免的八种习惯(TechTarget转载)
    索引维护对于保证查询能够总是受益于索引使用并减少 IO/RAM/CPU 是至关重要的
    SQL SERVER性能分析--死锁检测数据库阻塞语句
    怎样有效地跟踪SQL Server的阻塞问题?(网转)
    solr.net的使用
    利用HttpWebRequest实现实体对象的上传
  • 原文地址:https://www.cnblogs.com/baobeiqi-e/p/9884757.html
Copyright © 2011-2022 走看看