@Transactional注解事务不回滚的原因

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

常见坑点1:遇到检查异常时,事务开启,也无法回滚。 例如下面这段代码,用户依旧增加成功,并没有因为后面遇到检查异常而回滚!!

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

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

例如下面这样,就可以正常回滚:

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

常见坑点2: 在业务层捕捉异常后,发现事务不生效。 这是许多新手都会犯的一个错误,在业务层手工捕捉并处理了异常,你都把异常“吃”掉了,Spring自然不知道这里有错,更不会主动去回滚数据。
例如:下面这段代码直接导致用户新增的事务回滚没有生效。

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

推荐做法:在业务层统一抛出异常,然后在控制层统一处理。

@Transactional
public int insertUser(User user) throws Exception
{
    // 新增用户信息
    int rows = userMapper.insertUser(user);
    // 新增用户岗位关联
    insertUserPost(user);
    // 新增用户与角色管理
    insertUserRole(user);
    // 模拟抛出SQLException异常
    boolean flag = true;
    if (flag)
    {
        throw new RuntimeException("发生异常了..");
    }
    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,……}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值