说明:业务需求是批量调拨,这些调拨的数据的数据,如果单条成功了,提交事务,就继续执行下一条;如果失败了,也不影响下一条的执行,最后把成功和失败的结果记录上就OK;这就要保证for循环中每一条执行的事务一致性。
每一次循环中必须有一次手痛回滚或者提交的操作,是为了释放事务的资源;
代码为示例子代码,只要关注红色标注部分的代码即可;
@Autowired
private PlatformTransactionManager transactionManager;
/**
* 批量调拨(不是整个方法事务,支持循环代码块事务)
*
* @param fromNode
* @param toNode
* @param vehicleList
* @return
*/
@Override
public List<BatchAllotResultVo> batchAllot(String fromNode, String toNode, List<BaseVehicleListTo> vehicleList, AmpUser user) throws BizException {
log.info("********************批量调拨开始******************************");
log.info("出发VDC:{}", fromNode);
log.info("目的VDC:{}", toNode);
log.info("调拨数据总条数:{}",vehicleList.size());
Assert.hasLength(fromNode, "出发VDC不可以为空");
Assert.hasLength(toNode, "目的VDC不可以为空");
Assert.notEmpty(vehicleList, "车辆不可以为空");
VlBaseNode baseNode = feignHelper.getNodesByCode(toNode);
//调拨时间,每次调拨所有的调拨必须是同一个调拨时间,调拨历史会根据调拨时间和调拨操作人分组查询,确定一次调拨
LocalDateTime allotTime= LocalDateTime.now();
List<BatchAllotResultVo> resultVos = new ArrayList<>();
for (int i=0 ;i<vehicleList.size();i++) {
//每一次循环开启一个事务,出现异常手动关闭,没有异常手动提交事务
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); // 事物隔离级别,开启新事 务,这样会比较安全些。
TransactionStatus status = transactionManager.getTransaction(def);
BaseVehicleListTo v=vehicleList.get(i);
BatchAllotResultVo resultVo=new BatchAllotResultVo();
resultVo.setVehicleCode(v.getVehicleCode());
try {
log.info("********执行调拨第"+(i+1)+"条:{}", JSON.toJSONString(v));
//校验:CV没有绑定销售订单,VL没有未完成的释放,VL没有质损;
//(1) 更新CV系统所属VDC
boolean updateVdcRes= vehicleManager.updateVdc();
if(updateVdcRes){
log.info("(1):更新车辆主表所属VDC成功");
}else {
//手动开启事务回滚
transactionManager.rollback(status);
log.info("(1):更新车辆主表所属VDC失败");
resultVo.setResult(false);
resultVo.setDesc("失败:不存在该车辆,或者车辆的数据已经被修改,请重新调拨");
resultVos.add(resultVo);
continue;
}
//(2) 插入调拨历史
CvAllotHistory history = CvAllotHistory.builder().vehicleCode(v.getVehicleCode()).spu(v.getSpu()).skuCode(v.getSkuCode())
.skuName(v.getMaterialDesc()).allotFromNode(fromNode).allotToNode(toNode).allotTime(allotTime).createUser(user.getId().toString()).createUsername(user.getName()).build();
boolean saveHisRes= allotHistoryService.save(history);
if(saveHisRes){
log.info("(2):插入调拨历史成功");
}else {
//手动开启事务回滚
transactionManager.rollback(status);
log.info("(2):插入调拨历史失败,手动回滚");
resultVo.setResult(false);
resultVo.setDesc("失败:插入调拨历史失败,请重新调拨");
resultVos.add(resultVo);
continue;
}
//手动事务提交
transactionManager.commit(status);
resultVo.setResult(true);
resultVo.setDesc("成功");
resultVos.add(resultVo);
log.info("********执行调拨第"+(i+1)+"条完成,执行成功。");
} catch (RuntimeException e) {
log.error("系统异常",e);
transactionManager.rollback(status);
}
}
long secCount= resultVos.stream().filter(BatchAllotResultVo::isResult).count();
log.info("********************批量调拨结束,成功 "+secCount+" 条,失败 "+(vehicleList.size()-secCount)+" 条******************************");
return resultVos;
}