• @Transactional注解的使用以及try-catch捕获异常导致@Transactional注解失效的问题


    1、事务管理是应用系统开发中必不可少的一部分。在spring boot 中,使用事务非常简单,只要直接在方法上面加入@Transactional 就可以实现。

    2、SpringBoot项目会自动配置一个 DataSourceTransactionManager,所以我们只需在方法(或者类)加上 @Transactional 注解,就自动纳入 Spring 的事务管理了。

    如下在方法加上 @Transactional 注解:

    @Transactional
    public void insertUser() {
        User user = new User("张三");
        userMapper.insertOneUser(user);          //向数据库插入一条记录
        throw new RuntimeException("发生异常");   //手动模拟抛出异常
    }
    

    抛出异常之后,事务会自动回滚,数据不会插入到数据库。

    • 当Transaction内发生unchecked exception的时候,会自动rollback,但是当Transaction内发生checked exception时,是不会自动rollback的。
    • 如果使用try-catch捕获异常,则该事务不会回滚。

    3、默认spring事务只在发生未被捕获的 RuntimeException 时才回滚。

    spring aop异常捕获原理:被拦截的方法需显式抛出异常,并不能经任何处理,这样aop代理才能捕获到方法的异常,才能进行回滚,默认情况下aop只捕获RuntimeException的异常,但可以通过配置来捕获特定的异常并回滚。
    换句话说在service的方法中不使用try catch或者在catch中最后加上throw new runtimeexcetpion(),这样程序异常时才能被aop捕获进而回滚。

    解决方案:

    • 方案1.例如service层处理事务,那么service中的方法中不做异常捕获,或者在catch语句中最后增加throw new RuntimeException()语句,以便让aop捕获异常再去回滚,并且在service上层(webservice客户端,view层action)要继续捕获这个异常并处理。

    • 方案2.在service层方法的catch语句中增加:TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();语句,手动回滚,这样上层就无需去处理异常。

    例如

    catch (Exception e)
    {
        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();//手动回滚
        result.put("status", 0);
        result.put("msg",msg);
        return result;
    }
    

    4、总结:如果是try-catch捕获异常引起的@Transactional注解失效,只要手动抛出RuntimeException()或者在catch中使用TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();语句就可以解决。

    5、参考博客:

  • 相关阅读:
    数据结构与算法(二)(栈、队列)
    数据结构与算法(一)(数组、线性查找、二分查找)
    ssm项目中常用的上传文件
    安全防御之防xss、SQL注入、与CSRF攻击
    int i=i++;和i=++i;和i++
    关于@Autowired和@Resource注解区别
    通过idea创建Maven项目整合Spring+spring mvc+mybatis
    深入理解java虚拟机(一)
    java中栈,堆,方法区
    SpringBoot+mybatis配置pagehelper实现基础分页
  • 原文地址:https://www.cnblogs.com/myblog001/p/13191729.html
Copyright © 2020-2023  润新知