最近在做导出excel优化,就把查询BD改成了查ES,并且使用了线程池。就出现了导出数据的条数对不上的问题。最终发现easy-es在分页的时候往传入的wrapper中设置的from和size,由于使用线程池传入的wrapper是同一个就出现了数据安全问题,所有就此记录一下问题,在使用线程池时一定要注意线程安全。
// 这是Easy-Es框架封装的分页查询方法
public EsPageInfo<T> pageQuery(Wrapper<T> wrapper, Integer pageNum, Integer pageSize) {
// 兼容分页参数
pageNum = pageNum == null || pageNum <= BaseEsConstants.ZERO ? BaseEsConstants.PAGE_NUM : pageNum;
pageSize = pageSize == null || pageSize <= BaseEsConstants.ZERO ? BaseEsConstants.PAGE_SIZE : pageSize;
wrapper.from = (pageNum - 1) * pageSize;
wrapper.size = pageSize;
// 请求es获取数据
SearchResponse response = getSearchResponse(wrapper);
// 解析数据
SearchHit[] searchHits = parseSearchHitArray(response);
List<T> dataList = Arrays.stream(searchHits)
.map(searchHit -> parseOne(searchHit, wrapper))
.collect(Collectors.toList());
long count = parseCount(response, Objects.nonNull(wrapper.distinctField));
return PageHelper.getPageInfo(dataList, count, pageNum, pageSize);
}
ambdaEsQueryWrapper<BizEsWaybillEntity> countWrapper = new LambdaEsQueryWrapper<>();
getEsQueryParam(query,countWrapper);
Long countTime = System.currentTimeMillis();
Integer totalCount = esWaybillMapper.selectCount(countWrapper).intValue();
log.info("查询es运单总条数:{}条,耗时:{}毫秒",totalCount, System.currentTimeMillis() - countTime);
totalNum = totalCount / pageSize + 1;
if (totalNum > 1) {
List<CompletableFuture<Integer>> futureList = new ArrayList<>();
ExcelWriter finalExcelWriter = excelWriter;
for (Integer i = 0; i < totalNum; i++) {
Integer finalI = i + 1;
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
// easy-es中的分页参数是往传入的wrapper中赋值,所有使用线程池并发每次查询都需要传入新的wrapper
LambdaEsQueryWrapper<BizEsWaybillEntity> wrapper = new LambdaEsQueryWrapper<>();
getEsQueryParam(query,wrapper);
List<BizEsWaybillEntity> bizWaybillVos = getBizEsWaybillEntities(wrapper, finalI, pageSize, finalExcelWriter, writeSheet);
return CollectionUtils.isNotEmpty(bizWaybillVos) ? bizWaybillVos.size() : 0;
}, downloadTaskExecutor);
futureList.add(future);
}
// 等待所有任务完成
allOf(futureList, startTime);
} else {
List<BizEsWaybillEntity> bizWaybillVos = getBizEsWaybillEntities(countWrapper, 1, pageSize, excelWriter, writeSheet);
log.info("导出运单数量:{},耗时:{}", bizWaybillVos.size(), System.currentTimeMillis() - startTime);
}