- 注入事务管理器
@Autowired
private PlatformTransactionManager transactionManager;
- 案例代码
/**
* 通过excel导入数据
*
* @param
* @param
* @return
*/
@RequestMapping(value = "/importExcelOut", method = RequestMethod.POST)
@Transactional
public Result<?> importExcelOut(@RequestParam("file") MultipartFile file, Container param) {
List<Container> containerList = new ArrayList<>();
AtomicReference<String> errorMessage=new AtomicReference<>();
try {
List<ExportContainer> list = super.importExcelNormal(file, ExportContainer.class);
/*去掉为空值的对象*/
ExportContainer query = new ExportContainer();
list=list.stream().filter(p->!query.equals(p)).collect(Collectors.toList());
if (CollectionUtils.isEmpty(list)) {
return Result.error("文件中不存在数据");
}
//基础数据,用于反向查找
List<Routes> routesList = routesService.list();
List<Port> portList = portService.list();
List<ContainerSize> containerSizeList = containerSizeService.list();
List<ContainerType> containerTypeList = containerTypeService.list();
List<CustomerCom> customerComList = customerComService.list();
SysDepart sysDepart = Optional.ofNullable(sysDepartService.getById(param.getDeptId())).orElse(new SysDepart());
int a = list.size();
int count=a%10!=0?(a/10)+1:a/10;
//主线程
CountDownLatch mainThreadLatch = new CountDownLatch(count);
//子线程
CountDownLatch rollBackLatch = new CountDownLatch(1);
AtomicBoolean rollbackFlag=new AtomicBoolean(false);
ExecutorService executorService = Executors.newFixedThreadPool(count);
for(int b=0;b<count;b++){
int c=a-(b*10)>10?(b+1)*10:a;
List<ExportContainer> expList = list.subList(b*10,c);
executorService.submit(()->{
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); // 事物隔离级别,开启新事务,这样会比较安全些。
TransactionStatus status = transactionManager.getTransaction(def); // 获得事务状态
try {
for (ExportContainer container : expList){
importExceOutAdd(container,routesList,portList,sysDepart,containerTypeList,containerSizeList,customerComList,containerList);
}
mainThreadLatch.countDown();
rollBackLatch.await();
if (rollbackFlag.get()) {
transactionManager.rollback(status);
}else{
transactionManager.commit(status);
}
}catch (Exception e){
e.printStackTrace();
mainThreadLatch.countDown();
rollbackFlag.set(true);
rollBackLatch.countDown();
errorMessage.getAndSet(e.getMessage());
transactionManager.rollback(status);
}
});
}
mainThreadLatch.await();
rollBackLatch.countDown();
} catch (Exception e) {
log.error(e.getMessage(), e);
return Result.error("文件导入失败:" + e.getMessage());
} finally {
try {
file.getInputStream().close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (StringUtils.isNotBlank(errorMessage.get())){
return Result.error("文件导入失败:" + errorMessage.get());
}
return Result.OK("文件导入成功!数据行数:" + containerList.size());
}
- 代码讲解
主要是用了两个CountDownLatch控制主子线程的交互。
01.mainThreadLatch控制主线程的执行,rollBackLatch控制子线程的运行,每运一次子线程mainThreadLatch就减一。当mainThreadLatch减完的时候rollBackLatch减一。子线程就会接着运行。
02.子线程手动事务回滚
事务管理器手动创建事务。捕获异常后手动回滚