//注入线程池和事务管理器
@Autowired
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
@Autowired
private DataSourceTransactionManager transactionManager;
/**
* 这里使用了线程池,异步执行保存商品清单和生成订单操作,由此引发了多线程事务回滚问题和多线程SecurityContext传递问题,具体解决办法看代码
* 如果出现了其他的新问题,实在解决不了,可以转为串行执行,业务代码已在注释标注
* @param bo 定标申请新增业务对象
* @return 操作结果
*/
public Boolean insertByBoSync(TenderCalibrationBo bo){
//线程计数器
CountDownLatch countDownLatch = new CountDownLatch(2);
//线程报错标记
AtomicBoolean isError = new AtomicBoolean(false);
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
TransactionStatus status = transactionManager.getTransaction(def);
//类转换
TenderCalibration add = BeanUtil.toBean(bo, TenderCalibration.class);
validEntityBeforeSave(add);
//查询商品清单
Long recordId = bo.getRecordId();
TenderRecordVo tenderRecordVo = tenderRecordService.queryById(recordId);
List<TenderRecordGoodsVo> tenderRecordVoGoodsList = tenderRecordVo.getGoodsList();
Assert.notEmpty(tenderRecordVoGoodsList,"所属定标记录商品清单不存在,请核对");
List<TenderCalibrationGoodsBo> goodsList = BeanCopyUtils.copyList(tenderRecordVoGoodsList, TenderCalibrationGoodsBo.class);
try {
//保存操作
save(add);
} catch (Exception e) {
log.info("主线程报错{}",e.getMessage());
isError.set(true);
e.printStackTrace();
}
bo.setGoodsList(goodsList);
if (!isError.get()) {
SecurityContext context = SecurityContextHolder.getContext();
//获取定标id
Long id = add.getId();
//批量新增
threadPoolTaskExecutor.execute(new Runnable() {
@Override
public void run() {
log.info("商品清单保存线程任务开始执行");
//为新线程赋值SecurityContext
SecurityContextHolder.setContext(context);
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
TransactionStatus status = transactionManager.getTransaction(def);
try {
//批量保存商品清单
//这里是实际业务执行代码,如果多线程问题解决不了,需要串行执行的话,直接拿这行代码即可
tenderCalibrationGoodsService.saveBoBatch(goodsList,id);
} catch (Exception e) {
log.info("商品清单保存线程报错{}",e.getMessage());
isError.set(true);
e.printStackTrace();
}
countDownLatch.countDown();
try {
countDownLatch.await();
SecurityContextHolder.clearContext();
if (isError.get()){
log.info("商品清单保存回滚");
transactionManager.rollback(status);
}else {
log.info("商品清单保存提交");
transactionManager.commit(status);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("商品清单保存线程执行完毕");
}
});
//生成订单
threadPoolTaskExecutor.execute(new Runnable() {
@Override
public void run() {
log.info("订单生成线程任务开始执行");
//为新线程赋值SecurityContext
SecurityContextHolder.setContext(context);
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
TransactionStatus status = transactionManager.getTransaction(def);
try {
//生成订单
//这里是实际业务执行代码,如果多线程问题解决不了,需要串行执行的话,直接拿这行代码即可
createOrder(bo,tenderRecordVo);
} catch (Exception e) {
log.info("订单生成线程报错{}",e.getMessage());
isError.set(true);
e.printStackTrace();
}
countDownLatch.countDown();
try {
countDownLatch.await();
SecurityContextHolder.clearContext();
if (isError.get()){
log.info("订单生成线程回滚");
transactionManager.rollback(status);
}else {
log.info("订单生成线程提交");
transactionManager.commit(status);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("订单生成线程执行完毕");
}
});
try {
countDownLatch.await();
if (isError.get()){
log.info("主线程回滚");
transactionManager.rollback(status);
}else {
log.info("主线程提交");
transactionManager.commit(status);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("主线程执行完毕");
}
return !isError.get();
}