标签:阿里巴巴 保存数据 对象 解析失败 单元 cto 线程安全 安全 end
导入的话比较简单了,参照官方文档,有好几个Demo。
我这里主要考虑几个情况: ①数据量较大,分批读取 ②数据格式需要校验,因为导入的数据有可能存在格式问题,但是需要给前端提醒一下哪里出错了.
一、Excel数据
这里在数字格式的地方用字符串导入,引起出错~
二、API 调用
这里参考官方文档,修改的地方在DemoExceptionListener监听类里面
/** * 数据转换等异常处理 * * <p> * 1. 创建excel对应的实体对象 参照{@link ExceptionDemoData} * <p> * 2. 由于默认异步读取excel,所以需要创建excel一行一行的回调监听器,参照{@link DemoExceptionListener} * <p> * 3. 直接读即可 */ @Test public void exceptionRead() { String fileName = "I:\\temp\\readDemo1.xlsx"; // 这里 需要指定读用哪个class去读,然后读取第一个sheet EasyExcel.read(fileName, ExceptionDemoData.class, new DemoExceptionListener()).sheet().doRead(); }
/** * 基础数据类.这里的排序和excel里面的排序一致 * **/ @Data public class ExceptionDemoData { private String string; private Date date; private Double doubleData; }
三、DemoExceptionListener监听类
主要内部定义一个存储异常信息的StringBuffer,用于收集异常,并在读取完Excel之后可以用于校验是否转换数据出错~
/** * 读取转换异常 * */ public class DemoExceptionListener extends AnalysisEventListener<ExceptionDemoData> { private static final Logger LOGGER = LoggerFactory.getLogger(DemoExceptionListener.class); /** * 每隔5条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收 */ private static final int BATCH_COUNT = 5; List<ExceptionDemoData> list = new ArrayList<ExceptionDemoData>(); //定义接收异常 private StringBuffer errorMsg; /** * 在转换异常 获取其他异常下会调用本接口。抛出异常则停止读取。如果这里不抛出异常则 继续读取下一行。 * * @param exception * @param context * @throws Exception */ @Override public void onException(Exception exception, AnalysisContext context) { LOGGER.error("解析失败,但是继续解析下一行:{}", exception.getMessage()); // 如果是某一个单元格的转换异常 能获取到具体行号 // 如果要获取头的信息 配合invokeHeadMap使用 if (exception instanceof ExcelDataConvertException) { ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException)exception; LOGGER.error("第{}行,第{}列解析异常,数据为:{}", excelDataConvertException.getRowIndex(), excelDataConvertException.getColumnIndex(), excelDataConvertException.getCellData()); String msg="第"+excelDataConvertException.getRowIndex()+"行,第"+excelDataConvertException.getColumnIndex()+"列解析异常,数据为:"+
excelDataConvertException.getCellData(); if(errorMsg==null){ errorMsg=new StringBuffer(); } //拼接报错信息 errorMsg.append(msg).append(System.lineSeparator()); } } /** * 这里会一行行的返回头 * * @param headMap * @param context */ @Override public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) { LOGGER.info("解析到一条头数据:{}", JSON.toJSONString(headMap)); } @Override public void invoke(ExceptionDemoData data, AnalysisContext context) { LOGGER.info("解析到一条数据:{}", JSON.toJSONString(data)); if (list.size() >= BATCH_COUNT) { //操作数据之前统一判断异常信息,可以直接抛异常 if (errorMsg != null && errorMsg.length() > 0) { // throw new RuntimeException("解析数据异常!!信息:"+errorMsg.toString()); LOGGER.error("解析数据异常!!信息:" + errorMsg.toString()); } saveData(); list.clear(); } } @Override public void doAfterAllAnalysed(AnalysisContext context) { ////操作数据之前统一判断异常信息 /*if (errorMsg != null && errorMsg.length() > 0) { // throw new RuntimeException("解析数据异常!!信息:"+errorMsg.toString()); LOGGER.error("解析数据异常!!信息:" + errorMsg.toString()); }else{ LOGGER.info("所有数据解析完成!"); //解析完成无错误保存数据 saveData(); }*/ } /** * 加上存储数据库 */ private void saveData() { LOGGER.info("{}条数据,开始存储数据库!", list.size()); LOGGER.info("存储数据库成功!"); } }
结果:
我这里每次读5行数据,如果调成读10条,这两个异常会合并到一起。
四、总结
这里不知道有没有线程安全和变量未回收问题。
标签:阿里巴巴 保存数据 对象 解析失败 单元 cto 线程安全 安全 end
原文地址:https://www.cnblogs.com/coloz/p/12559558.html