spring 中事务注解@Transactional与trycatch的使用

在项目中 @service层中 我们会经常在做一些增删改操作的方法上看到 spring 的事务注解 @Transactional已知@Transactional 是让spring 帮我们实现事务的控制。

但是在项目中会经常看到 有的方法中 会存在trycatch块包括的方法上注解
@Transactional

 @Override
     @Transactional
     public int add(AddReq aAddReq) {
    
    
     try{
    
    
     //增删改方法
         } catch (Exception e) {
    
    
             .....
             e.printStackTrace();}
// }
         return 1;
     }

上述的方法执行后可以看到事务并没有执行,再看一个例子:

  @Override
     @Transactional
     public int addOrder(AddReq aAddReq) {
    
    
     try{
    
    
     //增删改方法
         } catch (Exception e) {
    
    
             // 手动硬编码开启spring事务管理
             TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
             e.printStackTrace();}
// }
         return 1;
     }

上述方法执行后我们可以看到事务最后执行了,但实际上 事务 执行只是因为手动硬编码开启spring事务管理起了作用 而方法上的注解并没有起作用

接下来再看一个例子:

@Override
     @Transactional
     public int addOrder(AddReq aAddReq) {
    
    
     try{
    
    
     //增删改方法
         } catch (Exception e) {
    
    
            
             throw new RuntimeException();
             }
// }
         return 1;
     }

上述方法执行后我们可以看到事务是执行了的,但这里有个小细节:@Transactional不做任何配置 默认是对抛出的unchecked异常回滚,checked异常不会回滚,为了让所有异常都会让事务启动可以将 @Transactional配置为 @Transactional(rollbackFor = Exception.class)

解释:

spring的事务边界是在调用业务方法之前开始的,业务方法执行完毕之后来执行commit or rollback(spring默认取决于是否抛出runtime异常).
如果抛出runtime exception 并在你的业务方法中没有catch到的话,事务会回滚。
一般不需要在业务方法中catch异常,如果非要catch,在做完你想做的工作后(比如关闭文件等)一定要抛出runtime exception,否则spring会将你的操作commit,这样就会产生脏数据.所以你的catch代码是画蛇添足。

Spring 事务注解 @Transactional 本来可以保证原子性,如果事务内有报错的话,整个事务可以保证回滚,但是加上try catch或者事务嵌套,可能会导致事务回滚失败。
针对trycatch与@Transactional嵌套使用的结论总结如下:

结论一:对于@Transactional可以保证RuntimeException错误的回滚,如果想保证非RuntimeException错误的回滚,需要加上rollbackFor = Exception.class 参数。
结论二:try catch只是对异常是否可以被@Transactional 感知 到有影响。如果错误抛到切面可以感知到的地步,那就可以起作用。
结论三:
由于REQUIRED属性,“两个事务”其实是一个事务,处理能力看报错时刻,是否添加了处理非RuntimeException的能力。

猜你喜欢

转载自blog.csdn.net/weixin_56287335/article/details/125158465