场景:单个删除时,需要提示具体删除失败的原因;批量删除时,需要提示删除失败总数。单个删除A和批量删除B都调用同一个方法C,区别是单个删除时传入的业务id放到list中再调用删除方法,这样后续删除如果有改动只需要改删除方法C就行,不需要改动A和B。为了保持事务一致,需要在A和B方法上添加注解@Transactional。C方法上可以不添加。代码如下:
方法A:
@Transactional
@Override
public void remove(Long id) {
List<Long> businessIds = Collections.singletonList(id);
RemoveDto removeDto = getRemoveDto( businessIds);;
if(!CollectionUtils.isEmpty(removeDto.getErrorData())){
throw new Exception("删除失败");
}
}
方法B:
@Transactional
@Override
public RemoveDto removeBatch(List<Long> ids) {
return getRemoveDto(ids);
}
方法C:
private RemoveDto getRemoveDto(List<Long> ids) {
if (CollectionUtils.isEmpty(ids)){
throw new Exception( "请求参数不能为空");
}
int success = 0;
int fail = 0;
for (Long id: ids) {
Object savePoint = null;
try {
//设置回滚点
savePoint = TransactionAspectSupport.currentTransactionStatus().createSavepoint();
remove(id);//该方法只是删除数据和相关的业务逻辑,方法也不需要添加@Transactional,同时该方法和方法C可以不在同一个类中
success++;
}catch (Exception e){
fail++;
log.error("系统异常删除原因:"+ JSON.toJSONString(e));
if (savePoint != null) {
//回滚
TransactionAspectSupport.currentTransactionStatus().rollbackToSavepoint(savePoint);
}
}
}
return RemoveDto.builder().successCount(success).failCount(fail).build();
}
经过上述操作,可以在使用for循环删除数据时,如果有一条删除失败,会回滚失败的数据,并且不影响已经删除成功的数据和未删除的数据。