批量启动流程接口 - 保证事务回滚
批量启动流程接口 - 保证事务回滚
该接口用于批量启动流程,并通过提取方法和事务注解,确保循环过程中异常能够触发全部事务回滚,保证数据一致性。
原接口代码
@PostMapping('startProcessBatch')
public List<JsonResult> startProcessBatch(@ApiParam @RequestBody List<ProcessStartCmd> startCmdList) {
List<JsonResult> result = new ArrayList<>();
for (ProcessStartCmd startCmd : startCmdList) {
JsonResult jsonResult = handReq(startCmd);
if (!jsonResult.isSuccess()) {
result.add(jsonResult);
continue;
}
BpmDef bpmDef = (BpmDef) jsonResult.getData();
boolean hasRight = systemClient.findAuthRight('BPM', 'def.start', bpmDef.getTreeId());
if (!hasRight) {
result.add(JsonResult.Fail('你没有启动权限!'));
continue;
}
String operate = startCmd.isHasPk() ? ProcessStartCmd.OPERATE_LIVE : ProcessStartCmd.OPERATE_START;
try {
//启动流程
BpmInst bpmInst = bpmInstService.doStartProcess(startCmd, bpmDef, operate);
jsonResult.setDetailMsg(JSON.toJSON(startCmd.getVars()).toString());
//发送任务消息通知
messageService.sendMsg();
result.add(jsonResult.setData(bpmInst)
.setSuccess(true).setMessage('成功启动流程!'));
} catch (Exception e) {
bpmInstService.handStartException(e);
result.add(null);
}
}
return result;
}
问题分析
由于该接口在循环体中执行了多个操作,如果在循环过程中发生异常,可能导致部分流程启动成功,而其他流程启动失败,数据不一致。
修改后的代码
为了保证在循环过程中报错会触发全部的事务回滚,可以将循环体内的代码块提取为一个独立的方法,并在该方法上添加事务注解。然后在循环体内调用该方法即可。
@PostMapping('startProcessBatch')
public List<JsonResult> startProcessBatch(@ApiParam @RequestBody List<ProcessStartCmd> startCmdList) {
List<JsonResult> result = new ArrayList<>();
for (ProcessStartCmd startCmd : startCmdList) {
try {
JsonResult jsonResult = startProcess(startCmd);
result.add(jsonResult);
} catch (Exception e) {
result.add(null);
}
}
return result;
}
@Transactional(rollbackFor = Exception.class)
public JsonResult startProcess(ProcessStartCmd startCmd) {
JsonResult jsonResult = handReq(startCmd);
if (!jsonResult.isSuccess()) {
return jsonResult;
}
BpmDef bpmDef = (BpmDef) jsonResult.getData();
boolean hasRight = systemClient.findAuthRight('BPM', 'def.start', bpmDef.getTreeId());
if (!hasRight) {
return JsonResult.Fail('你没有启动权限!');
}
String operate = startCmd.isHasPk() ? ProcessStartCmd.OPERATE_LIVE : ProcessStartCmd.OPERATE_START;
try {
//启动流程
BpmInst bpmInst = bpmInstService.doStartProcess(startCmd, bpmDef, operate);
jsonResult.setDetailMsg(JSON.toJSON(startCmd.getVars()).toString());
//发送任务消息通知
messageService.sendMsg();
return jsonResult.setData(bpmInst)
.setSuccess(true).setMessage('成功启动流程!');
} catch (Exception e) {
bpmInstService.handStartException(e);
throw e;
}
}
说明
@Transactional(rollbackFor = Exception.class)注解用于指定方法为事务方法,并设置回滚异常类型为Exception,表示任何异常都会触发回滚。- 通过将循环体内的代码提取为
startProcess方法,并将事务注解应用于该方法,可以保证在循环过程中如果发生异常,将会触发全部的事务回滚。 - 在
startProcess方法中,使用throw e将异常抛出,以便事务回滚机制能够正常工作。
原文地址: https://www.cveoy.top/t/topic/qeqg 著作权归作者所有。请勿转载和采集!