searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

如何解决Spring事务异常回滚

2023-07-20 10:04:04
34
0

Spring aop的异常捕获原理:被拦截的方法需显式抛出异常,并不能经任何处理,这样aop代理才能捕获到方法的异常,才能进行回滚。默认情况下aop只捕获runtimeexception的异常,但可以通过配置来捕获特定的异常并回滚。 

例如用户新增需要插入用户表和用户角色表,如果出现异常需要回滚所有操作以防止产生脏数据,解决方案如下:

方案1:service层统一抛出异常,如不做异常捕获,或者在catch语句中最后增加throw new RuntimeException()语句,以便让aop捕获异常再去回滚 ,并且在Controller层统一捕获异常并处理。     
        try {
            userDao.save(user);
            saveUserRole(user);
        } catch (Exception e) {
            logger.info("新增用户接口异常,异常信息:"+e);
            throw new RuntimeException();
        }

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

        try {
            userDao.save(user);
            saveUserRole(user);
        } catch (Exception e) {
            logger.info("新增用户接口异常,异常信息:"+e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }

方案3(推荐):在所在的方法上使用@Transactional注解,加上rollbackFor属性明确异常 ,形如:@Transactional(rollbackFor = Exception.class),实现异常回滚。

    @Transactional(rollbackFor = Exception.class)
    pubilc void saveUser(User user) throw Exception{
        userDao.save(user);
        saveUserRole(user);
    }
 
使用@Transactional的注意事项:
1.可以被应用于接口定义、接口方法以及类、类的方法上, 但是Spring官方不建议接口或者接口方法上使用该注解,因为这只有在使用基于接口的代理时它才会生效。另外,@Transactional注解应该只被应用到public可见性上才不会无效,而且建议注解放在方法级别,即在实现类的方法上使用。
2.使用了@Transactional的方法,对同一个类里面的方法调用, @Transactional无效。
3.在方法里没有try catch抓异常时,被调用的方法入口处如果没有加事务注解,那么方法内调用其他的方法(不管其他方法前面有没有加事务注解),其他的方法的事务都不会生效;被调用的方法入口处如果加了事务注解,那么方法内调用其他的方法(不管其他方法前面有没有加事务注解),其他的方法的事务都会生效。
4. @Transactional 注解标识的方法,处理过程尽量的简单。尤其是带锁的事务方法,能不放在事务里面的最好不要放在事务里面。可以将常规的数据库查询操作放在事务前面进行,而事务内进行增、删、改、加锁查询等操作。
0条评论
0 / 1000
韩****萍
2文章数
0粉丝数
韩****萍
2 文章 | 0 粉丝
韩****萍
2文章数
0粉丝数
韩****萍
2 文章 | 0 粉丝
原创

如何解决Spring事务异常回滚

2023-07-20 10:04:04
34
0

Spring aop的异常捕获原理:被拦截的方法需显式抛出异常,并不能经任何处理,这样aop代理才能捕获到方法的异常,才能进行回滚。默认情况下aop只捕获runtimeexception的异常,但可以通过配置来捕获特定的异常并回滚。 

例如用户新增需要插入用户表和用户角色表,如果出现异常需要回滚所有操作以防止产生脏数据,解决方案如下:

方案1:service层统一抛出异常,如不做异常捕获,或者在catch语句中最后增加throw new RuntimeException()语句,以便让aop捕获异常再去回滚 ,并且在Controller层统一捕获异常并处理。     
        try {
            userDao.save(user);
            saveUserRole(user);
        } catch (Exception e) {
            logger.info("新增用户接口异常,异常信息:"+e);
            throw new RuntimeException();
        }

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

        try {
            userDao.save(user);
            saveUserRole(user);
        } catch (Exception e) {
            logger.info("新增用户接口异常,异常信息:"+e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }

方案3(推荐):在所在的方法上使用@Transactional注解,加上rollbackFor属性明确异常 ,形如:@Transactional(rollbackFor = Exception.class),实现异常回滚。

    @Transactional(rollbackFor = Exception.class)
    pubilc void saveUser(User user) throw Exception{
        userDao.save(user);
        saveUserRole(user);
    }
 
使用@Transactional的注意事项:
1.可以被应用于接口定义、接口方法以及类、类的方法上, 但是Spring官方不建议接口或者接口方法上使用该注解,因为这只有在使用基于接口的代理时它才会生效。另外,@Transactional注解应该只被应用到public可见性上才不会无效,而且建议注解放在方法级别,即在实现类的方法上使用。
2.使用了@Transactional的方法,对同一个类里面的方法调用, @Transactional无效。
3.在方法里没有try catch抓异常时,被调用的方法入口处如果没有加事务注解,那么方法内调用其他的方法(不管其他方法前面有没有加事务注解),其他的方法的事务都不会生效;被调用的方法入口处如果加了事务注解,那么方法内调用其他的方法(不管其他方法前面有没有加事务注解),其他的方法的事务都会生效。
4. @Transactional 注解标识的方法,处理过程尽量的简单。尤其是带锁的事务方法,能不放在事务里面的最好不要放在事务里面。可以将常规的数据库查询操作放在事务前面进行,而事务内进行增、删、改、加锁查询等操作。
文章来自个人专栏
Java基础
2 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
0
0