背景
分批读取大量数据的excel文件,每次读取1000行数据,然后插入数据库,并且去执行一个方法,执行完毕后更新此行数据的状态。需要获取已更新数据的占比,即计算百分比。
因为是分批读取的,我们不可以直接用已更新状态数量/数据库中总数。因为可能一次读取的1000行数据更新状态很快,直接1000/1000 * 100=100%了。
但实际上excel文件中实际有1w行数据,那么我们要获取excel的总行数。
方法
使用easyexcel获取总行数,记录一下,
在创建监听器时,重写invoke方法时,使用下面代码获取总行数(含表头):
public void invoke(DemoData data, AnalysisContext context) { // 获取总行数(含表头) Integer rowNumber = context.readSheetHolder().getApproximateTotalRowNumber(); }
目前只能获取大概的条数(每个excel都会记录一个总条数,但是这个总条数由于各种空行等原因,不一定正确),无法精确获取,要精确获取的自己在监听器里面一条条统计
监听器举例:
// 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去 @Slf4j public class DemoDataListener implements AnalysisEventListener<DemoData> { /** * 批处理阈值100 */ private static final int BATCH_COUNT = 100; /** * 缓存的数据 */ private List<DemoData> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT); /** * 假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。 */ private DemoDAO demoDAO; public DemoDataListener() { // 这里是demo,所以随便new一个。实际使用如果到了spring,请使用下面的有参构造函数 demoDAO = new DemoDAO(); } /** * 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来 * * @param demoDAO */ public DemoDataListener(DemoDAO demoDAO) { this.demoDAO = demoDAO; } /** * 这个每一条数据解析都会来调用 * * @param data one row value. Is is same as {@link AnalysisContext#readRowHolder()} * @param context */ @Override public void invoke(DemoData data, AnalysisContext context) { Integer rowNumber = analysisContext.readSheetHolder().getApproximateTotalRowNumber(); // 设置execl最多2000行(含表头) if (rowNumber > 2000) { throw new ExcelAnalysisException("超出总行数限制,总行数为:" + rowNumber); } log.info("解析到一条数据:{}", JSON.toJSONString(data)); cachedDataList.add(data); // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM if (cachedDataList.size() >= BATCH_COUNT) { saveData(); // 存储完成清理 list cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT); } } /** * 所有数据解析完成了 都会来调用 * * @param context */ @Override public void doAfterAllAnalysed(AnalysisContext context) { // 这里也要保存数据,确保最后遗留的数据也存储到数据库 saveData(); log.info("所有数据解析完成!"); } /** * 加上存储数据库 */ private void saveData() { log.info("{}条数据,开始存储数据库!", cachedDataList.size()); demoDAO.save(cachedDataList); log.info("存储数据库成功!"); } }
本篇文章如有帮助到您,请给「翎野君」点个赞,感谢您的支持。