事务@Transactional@Transactional注解的rollbackFor属性

Posted aaacarrot

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了事务@Transactional@Transactional注解的rollbackFor属性相关的知识,希望对你有一定的参考价值。

背景:

代码是这样写的:

@Service
@Transactional
public class LoginBizImpl implements LoginBiz 
	// .... 省略

阿里巴巴规范扫描,
它就提示attribute rollbackfor of annotation translation must be set

问题说明

嗯,查了一下,大意是这样子的

1、spring 或 springboot 框架下,使用 @Transactional 可以开启事务,期望值是当发生异常的时候,就进行事务回滚。但是呢,通过这个注解进行事务管理,只有在遇到运行时异常和Error 的时候才会回滚,非运行时异常不回滚

2、但我们的期望是,事务中无论出现 Error,运行时异常,还是非运行时异常,都可以回滚,可以这样做:
@Transactional(rollbackFor = Exception.class)
@Transactional(rollbackFor = Exception.class)可以实现, Exception 及其子类的异常都会触发回滚,并且不会影响Error 的回滚。 换言之,就是所有的异常,都能回滚了(因为Error 和 运行时异常本来是能回滚的,加这么一个,非运行时异常也能回滚,就齐活了)
(所以 spring 为什么默认只针对 error 和 运行时异常回滚呢。。。是因为非运行时异常,本应该被处理掉?)

3、补充一些知识,什么是Error, 什么是运行时异常,什么是非运行时异常?

java的异常模型,Throwable是最顶层的父类,有Error和Exception两个子类。

Error表示严重的错误(如OOM等);
Exception可以分为运行时异常(RuntimeException及其子类)和非运行时异常(Exception的子类中,除了RuntimeException及其子类之外的类)。

非运行时异常是检查异常(checked exceptions),一定要try catch,因为这类异常是可预料的,编译阶段就检查的出来;
Error和运行时异常是非检查异常(unchecked exceptions),不需要try catch,因为这类异常是不可预料的,编辑阶段不会检查,没必要检查,也检查不出来

嗯,大概就是这样子了。

关于@Transactional注解的一些实验

实验一

不加rollbackFor属性,抛出RuntimeException,正常回滚

@Transactional
public void save()
    StudentDO studentDO = new StudentDO();
    studentDO.setName("ltm");
    studentDO.setAge(22);
    studentMapper.insert(studentDO);

    throw new RuntimeException("我是异常");

实验二

不加rollbackFor属性,抛出IOException,不回滚

@Transactional
public void save() throws IOException
    StudentDO studentDO = new StudentDO();
    studentDO.setName("ltm");
    studentDO.setAge(22);
    studentMapper.insert(studentDO);

    throw new IOException();

实验三

加上rollbackFor = Exception.class,抛出IOException,正常回滚

@Transactional(rollbackFor = Exception.class)
public void save() throws IOException
    StudentDO studentDO = new StudentDO();
    studentDO.setName("ltm");
    studentDO.setAge(22);
    studentMapper.insert(studentDO);

    throw new IOException();

实验四

不加rollbackFor属性,抛出OutOfMemoryError,正常回滚

@Transactional()
public void save()
    StudentDO studentDO = new StudentDO();
    studentDO.setName("ltm");
    studentDO.setAge(22);
    studentMapper.insert(studentDO);

    throw new OutOfMemoryError();

实验五

加上rollbackFor = Exception.class,抛出OutOfMemoryError,正常回滚,说明rollbackFor = Exception.class不会覆盖Error的回滚

@Transactional(rollbackFor = Exception.class)
public void save()
    StudentDO studentDO = new StudentDO();
    studentDO.setName("ltm");
    studentDO.setAge(22);
    studentMapper.insert(studentDO);

    throw new OutOfMemoryError();


参考: https://www.jianshu.com/p/c5988db897fc

以上是关于事务@Transactional@Transactional注解的rollbackFor属性的主要内容,如果未能解决你的问题,请参考以下文章

数据库事务系列1 事务概述 事务分类

初识事务,事务隔离级别,事务传播行为

事务事务特性事务隔离级别spring事务传播特性

SQL中事务有几种?

Spring 事务控制-存储过程事务

什么叫mysql事务?