事务分析(一) 事务回滚

事务回滚分析 @Transaction rollbackfor


1.@Transactional的rollbackfor默认回滚异常

不设置rollbackfor时,默认遇到运行时异常(RuntimeException)才回滚事务,非运行时异常不会回滚

 2.只有@Transactional,运行时异常和非运行时异常回滚测试

情景1:运行时异常(异常抛出) java.lang.ArithmeticException: / by zero  

@Transactional
public void test1(){
userMapper.insert("LiLei",122);
System.err.println(1/0);
}

运行结果: 事务回滚 org.springframework.transaction.interceptor.TransactionInterceptor.invoke ,数据没有插入到数据库

情景2:运行时异常(异常捕获) java.lang.ArithmeticException: / by zero  

@Transactional
public void test1(){
    userMapper.insert("LiLei1",122);
    try {
        System.err.println(1/0);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

运行结果:事务未回滚,数据成功插入到数据库

情景3:运行时异常(异常捕获再抛出)

@Transactional
public void test1(){
    userMapper.insert("LiLei11",122);
    try {
        System.err.println(1/0);
    } catch (ArithmeticException e) {
        e.printStackTrace();
        throw e;
    }
}

运行结果: 事务回滚,数据没有插入到数据库

情景4:非运行时异常(异常抛出) java.lang.ClassNotFoundException: null 

@Transactional
public void test1() throws ClassNotFoundException {
    userMapper.insert("LiLei",122);
throw new ClassNotFoundException();
}

运行结果:事务未回滚,数据成功插入到数据库

情景5:非运行时异常(异常捕获) java.lang.ClassNotFoundException: null 

@Transactional
public void test1() {
    userMapper.insert("LiLi",122);
    try {
        throw new ClassNotFoundException();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
}

运行结果:事务未回滚,数据成功插入到数据库


 小结:

@Transactional 未设置 rollbackfor 时,默认识别运行时异常 RunTimeException() ,非运行时异常不会回滚,且RunTimeException()被捕获时不会触发事务回滚.

我们比较熟悉的RumtimeException类的子类有
Java.lang.ArithmeticException
Java.lang.ArrayStoreExcetpion
Java.lang.ClassCastException
Java.lang.IndexOutOfBoundsException
Java.lang.NullPointerException

 3.指定rollbackfor=Exception.class回滚测试

情景1:

@Transactional(rollbackFor = Exception.class)
public void test1(){
userAdd2("Jobs",22);
}
public void userAdd2(String name,Integer age){
userMapper.insert(name,age);
try {
throw new NullPointerException();
} catch (NullPointerException e) {
e.printStackTrace();
}
}

运行结果:事务未回滚,数据成功录入

情景2:

@Transactional(rollbackFor = Exception.class)
public void test1(){
userAdd2("Jobs",22);
}
public void userAdd2(String name,Integer age){
userMapper.insert(name,age);
throw new NullPointerException();
}

运行结果:事务回滚,数据没有插入到数据库


小结:

这两个情景的测试结果很明显了,由步骤2的5个情景已经可以推测出结果

4.@Transactional()的回滚失效分析

 情况1:上边提到的异常被捕获处理,且 外层方法添加了事务 

 情况2:外层方法没添加事务

public void test1(){
userAdd1("Jobs",22);
}
@Transactional
public void userAdd1(String name,Integer age) {
userMapper.insert(name,age);
System.err.println(1/0);
}

运行结果:事务未回滚,数据成功插入到数据库

原因分析:

 AOP 使用的是动态代理的机制,它会给类生成一个代理类,事务的相关操作都在代理类上完成。内部方式使用this调用方式时,使用的是实例调用,并没有通过代理类调用方法,所以会导致事务失效

作者:往霄龙
求其上者得其中,求其中者得其下
原文地址:https://www.cnblogs.com/JQKA/p/11646743.html