为什么阿里规定需要在事务注解@Transactional中指定rollbackFor?

阿里巴巴Java规范:方法【edit】需要在Transactional注解指定rollbackFor或者在方法中显示的rollback。

异常的分类 img exception-1.png

img

Exception.png

Throwable:有两个重要的子类:Exception(异常)和Error(错误),二者都是Java异常处理的重要子类,各自都包含大量子类。

Error(错误):是程序无法处理的错误,表示运行应用程序中较严重问题。大多数错误与代码编写者执行的操作无关,而表示代码运行时JVM (Java虚拟机)出现的问题。例如。Java虚拟机运行错误(Virtual MachineError),当JVM不再有继续执行操作所需要的内存资源时,将出现 OutOfMemoryError 。这些异常发生时,Java虚拟机(JVM)一般会选择线程终止。

Exception(异常):是程序本身可以处理的异常。他又分为运行时异常RuntimeException和非运行时异常。

error和exception有什么区别

error表示恢复不是不可能但很困难的情况下的一种严重问题。 比如说内存溢出。不可能指望程序能处理这样的情况。exception表示一种设计或实现问题。也就是说,它表示如果程序运行正常,从不会发生的情况。

运行时异常

都是RuntimeException类及其子类异常,如NullPointerException(空指针异常)、IndexOutOfBoundsException(下标越界异常)等,这些异常是非检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。

运行时异常的特点是Java编译器不会检查它,也就是说,当程序中可能出现这类异常,即使没有用try-catch语句捕获它,也没有用throws子句声明抛出它,也会编译通过。

常见的运行时异常:

ArithmeticException——由于除数为0引起的异常;

ArrayStoreException——由于数组存储空间不够引起的异常;

ClassCastException—一当把一个对象归为某个类,但实际上此对象并不是由这个类 创建的,也不是其子类创建的,则会引起异常;

IllegalMonitorStateException——监控器状态出错引起的异常;

NegativeArraySizeException—一数组长度是负数,则产生异常;

NullPointerException—一程序试图访问一个空的数组中的元素或访问空的对象中的 方法或变量时产生异常; OutofMemoryException——用new语句创建对象时,如系统无法为其分配内存空 间则产生异常;

SecurityException——由于访问了不应访问的指针,使安全性出问题而引起异常;

IndexOutOfBoundsExcention——由于数组下标越界或字符串访问越界引起异常;

IOException——由于文件未找到、未打开或者I/O操作不能进行而引起异常;

ClassNotFoundException——未找到指定名字的类或接口引起异常;

CloneNotSupportedException——一程序中的一个对象引用Object类的clone方法,但 此对象并没有连接Cloneable接口,从而引起异常;

InterruptedException—一当一个线程处于等待状态时,另一个线程中断此线程,从 而引起异常,有关线程的内容,将在下一章讲述;

NoSuchMethodException一所调用的方法未找到,引起异常;

Illega1AccessExcePtion—一试图访问一个非public方法;

StringIndexOutOfBoundsException——访问字符串序号越界,引起异常;

ArrayIdexOutOfBoundsException—一访问数组元素下标越界,引起异常;

NumberFormatException——字符的UTF代码数据格式有错引起异常;

IllegalThreadException—一线程调用某个方法而所处状态不适当,引起异常;

FileNotFoundException——未找到指定文件引起异常;

EOFException——未完成输入操作即遇文件结束引起异常。

非运行时异常

是RuntimeException以外的异常,类型上都属于Exception类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如IOException、SQLException等以及用户自定义的Exception异常,一般情况下不要自定义检查异常。

可查异常和不可查异常

可查的异常(checked exceptions):Exception下除了RuntimeException外的异常
不可查的异常(unchecked exceptions):RuntimeException及其子类和错误(Error)

如果不对运行时异常进行处理,那么出现运行时异常之后,要么是线程中止,要么是主程序终止。 如果不想终止,则必须捕获所有的运行时异常,决不让这个处理线程退出。

队列里面出现异常数据了,正常的处理应该是把异常数据舍弃,然后记录日志。不应该由于异常数据而影响下面对正常数据的处理。

非运行时异常是RuntimeException以外的异常,类型上都属于Exception类及其子类。如IOException、SQLException等以及用户自定义的Exception异常。

对于这种异常,JAVA编译器强制要求我们必需对出现的这些异常进行catch并处理,否则程序就不能编译通过。所以,面对这种异常不管我们是否愿意,只能自己去写一大堆catch块去处理可能的异常。

@Transactional 的写法

@Transactional如果只这样写,Spring框架的事务基础架构代码将默认地 只 在抛出运行时和unchecked exceptions时才标识事务回滚。也就是说,当抛出个RuntimeException 或其子类例的实例时。(Errors 也一样 - 默认地 - 标识事务回滚。)从事务方法中抛出的Checked exceptions将 不 被标识进行事务回滚。

  • 让checked例外也回滚
    @Transactional(rollbackFor=Exception.class)
  • 让unchecked例外不回滚
    @Transactional(notRollbackFor=RunTimeException.class)
  • 不需要事务管理的(只查询的)方法
    @Transactional(propagation=Propagation.NOT_SUPPORTED)

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

关于使用注解@Transactional,手动抛出异常不回滚现象总结:

我用的是自定义异常直接继承Exception异常,在实际操作中,出现异常后没有回滚,还是把数据写入数据库了。

查了一下资料,只有runtimeexception并且没有被try catch处理的异常才会回滚。另外Transactional可以指定回滚异常,然后我用@Transactional(rollbackFor=Exception.class)就好使了。

总结@Transactional(rollbackFor=Exception.class)如果有异常,并且这个异常没有被try catch 就会回滚。