项目中必不可少会有excel 导入的需求。之前项目中excel的导入都是由组里的大佬通过组装poi包来实现的。
可是效率有点惨不忍睹,虽然还挺好用。。。,偶然使用了 easyexcel 才发现差距原来有点大。
依赖
<!-- easyexcel -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.1.6</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>3.17</version>
</dependency>
对比
大佬封装的方法
public static <T> List<T> parseExcelToObject(MultipartFile multipartFile, Class<T> clazz) throws RestApiException {
List<T> resultList = new ArrayList<>();
Field[] fields = getFields(clazz);
List<List<Cell>> parseList = parseExcel(multipartFile);
if (null == parseList || parseList.size() == 0) {
return resultList;
}
try {
for (List<Cell> cellList : parseList) {
T object = clazz.newInstance();
cellList.stream().forEach(e -> {
if (null != e) {
int index = e.getColumnIndex();
setFieldValue(object, fields[index], e);
}
});
resultList.add(object);
}
} catch (Exception e) {
log.warn("解析文件出错 e={}", e.getMessage());
throw new RestApiException(ErrorConstant.PARSE_IMPORT_FILE_ERROR, ErrorConstant.PARSE_IMPORT_FILE_ERROR_MSG);
}
return resultList;
}
基本上都是使用了原生的poi包的东西,没有进行二次封装。
使用了 easyexcel
的模板代码
@Override
@Transactional(rollbackFor = Exception.class)
public void excelImport(MultipartFile file) {
try {
BufferedInputStream bufferedInputStream = new BufferedInputStream(file.getInputStream());
EasyExcel.read(bufferedInputStream, xxx.class, new AnalysisEventListener<xxx>() {
List<xxx> list = new ArrayList();
@Override
public void invoke(xxx data, AnalysisContext context) {
log.info("解析到一条数据:{}", JSON.toJSONString(data));
//可以在此实现业务代码
list.add(data);
// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
if (list.size() >= BATCH_COUNT) {
saveData();
// 存储完成清理 list
list.clear();
}
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 这里也要保存数据,确保最后遗留的数据也存储到数据库
saveData();
log.info("所有数据解析完成!");
}
/**
* 加上存储数据库
*/
private void saveData() {
log.info("{}条数据,开始存储数据库!", list.size());
saveAll(list);
log.info("存储数据库成功!");
}
}).sheet().doRead();
} catch (IOException e) {
e.printStackTrace();
}
return true;
}
测试
数据量:390条数据
耗时:2215
耗时:242
差距在10倍左右。如果数据量增大的话,感觉差距可能会更大。。
未完待续…