• 事务分析(一) 事务回滚


    事务回滚分析 @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调用方式时,使用的是实例调用,并没有通过代理类调用方法,所以会导致事务失效

    作者:往霄龙
    求其上者得其中,求其中者得其下
  • 相关阅读:
    结对开发:电梯调度(2)
    小组站立会议
    小组站立会议
    小组站立会议
    小组站立会议4月15日
    小组站立会议
    小组站立会议
    团队个人每天详细计划汇总
    Spring冲刺计划会议
    团队项目开发
  • 原文地址:https://www.cnblogs.com/JQKA/p/11646743.html
Copyright © 2020-2023  润新知