美文网首页
事务@Transactional 和 统一处理异常

事务@Transactional 和 统一处理异常

作者: 小名源治 | 来源:发表于2022-11-29 18:17 被阅读0次

    在新建的Spring boot项目中,一般都会引用spring-boot-starter或者spring-boot-starter-web依赖,这两个依赖中都已经包含了spring-boot-starter-jdbcspring-boot-starter-data-jpa的依赖,因此我们不需要添加其他的依赖就可以正常使用@Transactional注解。

    注意:只有@Transactional只能应用到public可见度的方法上,可以被应用于接口定义和接口方法上,方法会覆盖类声明的事务

    如果一个用户注册的时候需要插入用户表,用户角色表,用户与用户关联表登多个表。如果成功那就一起成功,其中某步操作失败就回滚之前所有的操作,防止出现脏数据。这样的操作就可以用到事务!

    @Transactional
    public int insertUser(User user)
    {
        ......
    }
    

    遇到的问题1:

    遇到异常检查时,开启事务也无法回滚。
    程序执行过程中,用户添加了一半,然后抛出SQLException异常,异常后面的代码依旧没有被执行,也就是说@Transactional失去了作用

    @Transactional
    public int insertUser(User user) throws Exception
    {
        // 新增用户信息
        int rows = userMapper.insertUser(user);
        // 新增用户岗位关联
        insertUserPost(user);
           // 模拟抛出SQLException异常
        boolean flag = true;
        if (flag)
        {
            throw new SQLException("发生异常了..");
        }
    
        // 新增用户与角色管理
        insertUserRole(user);
    
        return rows;
    }
    

    原因分析:因为Spring的默认的事务规则是遇到运行时异常(RuntimeException)和程序错误异常(Error)才会回滚。如果想针对检查异常进行事务回滚,可以在@Transactional注解里使用 rollbackFor属性明确指定异常。

    image.png
    例如这样,就可以正常回滚
    @Transactional(rollbackFor = Exception.class)
    public int insertUser(User user) throws Exception
    {
        // 新增用户信息
        int rows = userMapper.insertUser(user);
        // 新增用户岗位关联
        insertUserPost(user);
           // 模拟抛出SQLException异常
        boolean flag = true;
        if (flag)
        {
            throw new SQLException("发生异常了..");
        }
    
        // 新增用户与角色管理
        insertUserRole(user);
    
        return rows;
    }
    

    Transactional注解的常用属性表:

    属性 说明
    propagation 事务的传播行为,默认值为 REQUIRED。
    isolation 事务的隔离度,默认值采用 DEFAULT
    timeout 事务的超时时间,默认值为-1,不超时。如果设置了超时时间(单位秒),那么如果超过该时间限制了但事务还没有完成,则自动回滚事务。
    read-only 指定事务是否为只读事务,默认值为 false;为了忽略那些不需要事务的方法,比如读取数据,可以设置 read-only 为 true。
    rollbackFor 用于指定能够触发事务回滚的异常类型,如果有多个异常类型需要指定,各类型之间可以通过逗号分隔。{xxx1.class, xxx2.class,……}
    noRollbackFor 抛出 no-rollback-for 指定的异常类型,不回滚事务。{xxx1.class, xxx2.class,……}

    事务的传播机制:
    事务的传播机制是指,当一个方法上添加了

    遇到的问题2:

    业务逻辑层遇到异常自己就捕获处理了,事务没有生效。
    自己用try catch捕获异常,异常已经被catch处理了,Spring自然不知道这里有异常,因此不会去主动回滚数据。

    @Transactional(rollbackFor = Exception.class)
    public int insertUser(User user) throws Exception
    {
        // 新增用户信息
        int rows = userMapper.insertUser(user);
        // 新增用户岗位关联
        insertUserPost(user);
           // 模拟抛出SQLException异常
        boolean flag = true;
            if (flag)
        {
            try
            {
                // 谨慎:尽量不要在业务层捕捉异常并处理
                throw new SQLException("发生异常了..");
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
        // 新增用户与角色管理
        insertUserRole(user);
    
        return rows;
    }
    

    解决办法:业务层我们只把异常抛出,在控制层捕获异常统一处理。

    统一异常处理

    相关文章

      网友评论

          本文标题:事务@Transactional 和 统一处理异常

          本文链接:https://www.haomeiwen.com/subject/mmudfdtx.html