zoukankan      html  css  js  c++  java
  • 【事务回滚与注解@Transactional 的测试demo】

    在项目中,@Transactional(rollbackFor=Exception.class),如果类加了这个注解,那么这个类里面的方法抛出异常,就会回滚,数据库里面的数据也会回滚。

    在@Transactional注解中如果不配置rollbackFor属性,那么事物只会在遇到RuntimeException的时候才会回滚,加上rollbackFor=Exception.class,可以让事物在遇到非运行时异常时也回滚

    默认spring事务只在发生未被捕获的 RuntimeExcetpion 时才回滚。也可以说spring会对unchecked异常进行事务回滚;如果是checked异常则不回滚。将派生于Error或者RuntimeException的异常称为unchecked异常,所有其他的异常成为checked异常。

    我是不是可以理解为 不加注解,发生空指针而不捕获时会发生回滚?(对不对需要进行下面验证)

     

    PS: @Transactional注解 应当应用于service层实现类或实现类中的public方法上,且如果为只读方法无需添加注解。

    PSS:着重测试注解属性:rollbackFor :用于指定能够触发事务回滚的异常类型,可以指定多个异常类型,常见的runtime异常:空指针异常,数组越界异常

     

    现将进行测试,测试的控制变量如下:

      1.添加注解@Transactional(rollbackFor = Exception.class)

      2.添加注解@Transactional(norollbackFor = Exception.class)

      3.捕获 runtime 异常

      4.不捕获 runtime 异常

      

     好了,开测:

      测试用例1:不添加@Transactional注解,测试异常为空指针异常,而捕获的是runtime异常,结果是 无回滚,无异常抛出,数据顺利更新。

       测试用例2:不添加@Transactional注解,测试异常为空指针异常,而捕获的是数组越界异常,结果是 无回滚,抛出空指针异常,数据可顺利更新。

      测试用例3:和测试用例2类似,但没有使用try-catch去捕获runtime异常,结果依旧是 没有回滚。

       测试用例4:添加@Transactional(rollbackFor = NullPointerException.class)注解,指定空指针类型异常,测试异常为空指针异常,而捕获的是数组越界异常,结果是 发生回滚, 数据无更新。

        测试用例5:添加@Transactional(rollbackFor = NullPointerException.class)注解,测试异常为空指针异常,而捕获的是Exception异常(包含空指针异常),结果是 不发生回滚, 数据有更新。

     

         测试用例6:添加@Transactional(norollbackFor = NullPointerException.class)注解,测试异常为空指针异常,而捕获的ArrayIndexOutOfBoundsException

    异常(包含空指针异常),结果是 不发生回滚, 数据有更新。

     好了,以上列举了6种情况,总结如下:

      1.当没有配置注解@Transactional时,spring默认是不开启事物管理的。

      2.配置注解后,回滚的前提是,try-catch捕获情况符合注解中参数的规范,且方法用public修饰,要求mysql数据库的引擎是InnoDB,因为只有InnoDB才是支持事务的( 可以用show variables like 'default_storage_engine'语句来查看数据库当前引擎)

      3.配置注解后,如果catch中捕获到了对应异常,那么即使配置注解也不会发生回滚。

      3.再次声明,unchecked exception–编译器不要求强制处置的异常,可以理解为 java.lang.RuntimeException类及它的子类都是非受查异常,如错误的类型转换异常:ClassCastException,下标越界异常:ArrayIndexOutOfBoundsException,空指针访问异常:NullPointerException,除零溢出异常:ArithmeticException等;

      4.注解属性:

    附:

    参考博客:https://www.cnblogs.com/clwydjgs/p/9317849.html

    spring aop 异常捕获原理:被拦截的方法需显式抛出异常,并不能经任何处理,这样aop代理才能捕获到方法的异常,才能进行回滚,默认情况下aop只捕获runtimeexception的异常,但可以通过配置来捕获特定的异常并回滚。

    在Spring FrameWork 的事务框架中推荐的事务回滚方法是,在当前执行的事务上下文中抛出一个异常。如果异常未被处理,当抛出异常调用堆栈的时候,Spring FrameWork 的事务框架代码将捕获任何未处理的异常,然后并决定是否将此事务标记为回滚。

    在默认配置中,Spring FrameWork 的事务框架代码只会将出现runtime, unchecked 异常的事务标记为回滚;也就是说事务中抛出的异常时RuntimeException或者是其子类,这样事务才会回滚(默认情况下Error也会导致事务回滚)。在默认配置的情况下,所有的 checked 异常都不会引起事务回滚。

    注:Unchecked Exception包括Error与RuntimeException. RuntimeException的所有子类也都属于此类。另一类就是checked Exception。

    Spring的事务管理默认是针对unchecked exception回滚,也就是默认对Error异常和RuntimeException异常以及其子类进行事务回滚,且必须对抛出异常,若使用try-catch对其异常捕获则不会进行回滚!(Error异常和RuntimeException异常抛出时不需要方法调用throws或try-catch语句);
    checked异常,checked异常必须由try-catch语句包含或者由方法throws抛出,且事务默认对checked异常不进行回滚。
    在service层若不加@Transactional则spring默认是不开启事物管理的。

    从源码来看,默认回滚的 类型确实是runtime异常和error

     

  • 相关阅读:
    2019.9.4 二维树状数组
    2019.9.4 简单题
    0052-YH的计算器
    0051-打乱顺序的三位数
    0050-计算天数
    0049-学校的上网费
    0048-三角形的判断
    0047-月份转换
    0046-简单的分段函数(二)
    0045-简单的分段函数(一)
  • 原文地址:https://www.cnblogs.com/dabuliu/p/15705752.html
Copyright © 2011-2022 走看看