上文说完了事务嵌套,那这里也不得不说下事务回滚是怎么回事。

spring声明式事务管理默认对非检查型异常和运行时异常进行事务回滚,而对检查型异常则不进行回滚操作。

1:首先说明一下异常是什么,有什么区分,以及常见的异常?

Java里面异常分为两大类:checkedexception(检查异常)和unchecked exception(未检查异常-也叫运行时异常RuntimeException)

对于未检查异常也叫RuntimeException(运行时异常),对于运行时异常,java编译器不要求你一定要把它捕获或者一定要继续抛出,但是对checkedexception(检查异常)要求你必须要在方法里面或者捕获或者继续抛出。

Thorwable是所有异常和错误的超类,

有两个子类Error和Exception,分别表示错误和异常。

其中异常类Exception又分为运行时异常(RuntimeException)和非运行时异常。

这两种异常有很大的区别,也称之为不检查异常(Unchecked Exception)和检查异常(Checked Exception)。

下面将详细讲述这些异常之间的区别与联系:

1、Error与Exception

Error是程序无法处理的错误,比如OutOfMemoryError、ThreadDeath等。

这些异常发生时,Java虚拟机(JVM)一般会选择线程终止。

Exception是程序本身可以处理的异常,这种异常分两大类运行时异常和非运行时异常。

程序中应当尽可能去处理这些异常。

2、运行时异常和非运行时异常

2.1:运行时异常都是RuntimeException类及其子类异常,

           如NullPointerException、IndexOutOfBoundsException等,

           这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。

           这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。

2.2:非运行时异常是RuntimeException以外的异常,类型上都属于Exception类及其子类。

           从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。

IOException、SQLException等以及用户自定义的Exception异常,一般情况下不自定义检查异常。

 

例如:常见的运行时异常,RuntimeException异常:

NullPointerException

ClassCastException

ArrayIndexOutOfBoundsException

StringIndexOutOfBoundsException

NumberFormatException

ArithmeticException   零做除数

这些也基本上就是平常代码运行阶段经常遇到的那些异常,其实都是RuntimeException的子类。

你如果不对运行时异常进行处理,那么出现运行时异常之后,要么是线程中止,要么是主程序终止。

 

检查异常 Checked ,一般在编译器就被检出,

           ClassNotFoundException

           NosuchFieldException

           NosuchMethodException

 

2:spring事务回滚

spring声明式事务管理默认对非检查型异常和运行时异常进行事务回滚,而对检查型异常则不进行回滚操作。

1Spring事务回滚机制是这样的:当所拦截的方法有指定异常抛出,事务才会自动进行回滚!

我们需要注意的地方有四点: 如果你在开发当中引入Spring进行事务管理,但是事务没能正常的自动回滚,可以对照下面四点,缺一不可!

①被截方法-—— 注解式:方法或者方法所在类被@Transactional注解;

                               拦截配置式:<tx:method />应该包含对该方法,名称格式的定义;

                                                                       且方法需要在expression定义的范围内;

②异常—— 该方法的执行过程必须出现异常,这样事务管理器才能被触发,并对此做出处理;

③指定异常——  默认配置下,事务只会对Error与RuntimeException及其子类这些UNChecked异常,做出回滚。  一般的Exception这些Checked异常不会发生回滚(如果一般Exception想回滚要做出配置);

④异常抛出—— 即方法中出现的指定异常,只有在被事务管理器捕捉到以后,事务才会据此进行事务回滚;

1,不捕捉,会回滚:没有trycatch

2,如果异常被try{}捕捉到,那么事务管理器就无法再捕捉异常,所以就无法做出反应,事务不回滚;

3,如果异常被try{}捕捉了,我们还可以在Catch(){}中throw   new  RuntimeException(),手动抛出运行时异常供事务管理器捕捉;       

2,在实际开发中,有时并没有异常发生,但是由于事务结果未满足具体业务需求,所以我们不得不手动回滚事务!

 有如下两种方法:

①手抛出异常(如果你没有配置一般异常事务回滚,请抛出运行时异常)  

throw new RuntimeException();

编程式实现手动回滚       

TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); 

注意:尽管可以采用编程式方法回滚事务,但“回滚”只是事务的生命周期之一,所以要么编程实现事务的全部必要周期,要么仍要配置事务切点,即,将事务管理的其他周期交由Spring的标识!

 

3:spring事务的默认配置

Spring的事务管理默认是针对unchecked exception(未检查 RuntimeException)回滚,也就是默认对Error异常和RuntimeException异常以及其子类进行事务回滚,且必须对抛出异常,若使用try-catch对其异常捕获则不会进行回滚!(Error异常和RuntimeException异常抛出时不需要方法调用throws或try-catch语句);

checked异常,checked异常必须由try-catch语句包含或者由方法throws抛出,且事务默认对checked异常不进行回滚。

 

在service类前加上@Transactional,声明这个service所有方法需要事务管理。每一个业务方法开始时都会打开一个事务。

Spring默认情况下会对运行期例外(RunTimeException)进行事务回滚。这个例外是unchecked

如果遇到checked意外就不回滚。

如何改变默认规则:

1 让checked例外也回滚:在整个方法前加上 @Transactional(rollbackFor=Exception.class)

2 让unchecked例外不回滚: @Transactional(notRollbackFor=RunTimeException.class)

3 不需要事务管理的(只查询的)方法:@Transactional(propagation=Propagation.NOT_SUPPORTED)

 

注意: 如果异常被try{}catch{}了,事务就不回滚了,如果想让事务回滚必须再往外抛try{}catch{throw Exception}。