SpringBoot学习示例——主动回滚,@Transactional注解捕获异常事务回滚,开发人员根据业务情况主动回滚
1. 不便利的@Transactional
我们在事务的开发中,会将常用的逻辑放在一个事务中,如果这个逻辑常用还好说,如果不常用的话就没必要单独拆出来放在另外的一个方法中,于是这种场景,@Transactional就没办法做到方法中的某个节点进行回滚。
若是拆成单独的事务方法,又没太大必要。
2. try...catch让@Transactional失效
正常情况下加注解@Transactional和try catch捕获异常会让注解失效。
我们开发的时候,也会出错,但是没必要全部回滚,就需要回滚到某个节点,@Transactional注解就无法满足我们这样的需求,那对于开发人员来说,就需要更好的解决方案。
3. 解决方案
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
使用这段代码,就能解决抛出的异常没有被@Transactional捕获异常的问题。因为有些异常我们是需要自己处理的。
@Transactional(rollbackFor = Exception.class)
public String fun() {
......service1......
try {
userMapper.delete(3);
User user = new User();
user.setId(2);
user.setName("jack");
userMapper.update(user);
int i = 1/0;
return "success";
} catch (Exception e) {
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
//其他服务逻辑
......service3......
}
如果像上面代码逻辑中,service1和service2之间的逻辑失败回滚了,但是会将service1的数据变更回滚掉,那如果我们不想回滚service1逻辑,继续执行service3,对于这种场景,上面的方式就没办法解决。
如果回滚可以回到某个节点,而且开发人员自己控制节点,那这样的需求就能完美解决,具体实现方式参考如下代码。
@Transactional(rollbackFor = Exception.class)
public String fun() {
......service1......
Object object = TransactionAspectSupport.currentTransactionStatus().createSavepoint();
try {
userMapper.delete(3);
User user = new User();
user.setId(2);
user.setName("jack");
userMapper.update(user);
int i = 1/0;
return "success";
} catch (Exception e) {
TransactionAspectSupport.currentTransactionStatus().rollbackToSavepoint(savePoint);
return e.getMessage();
}
//其他服务逻辑
......service3......
}
这里,我们在service1后打一个savepoint回滚点,如果出现问题,就回滚到这个savepoint,再继续执行后续的service3逻辑。
完美解决!
正文到此结束
- 本文标签: Spring Boot Spring Java
- 版权声明: 本站原创文章,于2021年02月02日由空白发布,转载请注明出处