背景
分批讀取大量數據的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("存儲數據庫成功!"); } }
本篇文章如有幫助到您,請給「翎野君」點個贊,感謝您的支持。