easyExcel 读取数据为空怎么办?
EasyExcel是一个基于Java的简单、省内存的读写Excel的开源项目。在尽可能节约内存的情况下支持读写百M的Excel。
github地址:https://github.com/alibaba/easyexcel
文档地址:EasyExcel · 语雀
目录
1、问题起因#
今天在帮助一位朋友解决easy Excel读取Excel表格信息时,程序反馈显示,读取内容为空,但是经过断点调试跟踪排查,发现程序能够读取到Excel里面的表头,以及行数等信息,唯一的问题就是读取到的实体类列表字段属性全部都是null,最后经过查阅相关资料得以解决问题。
由于这位朋友为了方便,使用lombok插件,其实本身使用lombok插件是没有问题的,但是由于使用不当,就有可能造成莫名奇妙的问题。在lombok中有一个注解为@Accessors(chain =
true
),
其中
chain的中文含义是链式的,设置为true,表示该实体对象支持链式编程,否则不支持链式编程。
2、源码片段#
private Object buildUserModel(Map<Integer, CellData> cellDataMap, ReadHolder currentReadHolder,
AnalysisContext context) {
ExcelReadHeadProperty excelReadHeadProperty = currentReadHolder.excelReadHeadProperty();
Object resultModel;
try {
resultModel = excelReadHeadProperty.getHeadClazz().newInstance();
} catch (Exception e) {
throw new ExcelDataConvertException(context.readRowHolder().getRowIndex(), 0,
new CellData(CellDataTypeEnum.EMPTY), null,
"Can not instance class: " + excelReadHeadProperty.getHeadClazz().getName(), e);
}
Map<Integer, Head> headMap = excelReadHeadProperty.getHeadMap();
Map<String, Object> map = new HashMap<String, Object>(headMap.size() * 4 / 3 + 1);
Map<Integer, ExcelContentProperty> contentPropertyMap = excelReadHeadProperty.getContentPropertyMap();
for (Map.Entry<Integer, Head> entry : headMap.entrySet()) {
Integer index = entry.getKey();
if (!cellDataMap.containsKey(index)) {
continue;
}
CellData cellData = cellDataMap.get(index);
if (cellData.getType() == CellDataTypeEnum.EMPTY) {
continue;
}
ExcelContentProperty excelContentProperty = contentPropertyMap.get(index);
Object value = ConverterUtils.convertToJavaObject(cellData, excelContentProperty.getField(),
excelContentProperty, currentReadHolder.converterMap(), currentReadHolder.globalConfiguration(),
context.readRowHolder().getRowIndex(), index);
if (value != null) {
map.put(excelContentProperty.getField().getName(), value);
}
}
BeanMap.create(resultModel).putAll(map);
return resultModel;
}
当Excel每行数据解析后, 会调用 buildStringList 将解析到的数据由Map转存到Bean中, 关键代码如下:
BeanMap.create(resultModel).putAll(map);
可见, EasyExcel是使用 net.sf.cglib.beans.BeanMap
工具类拷贝的, 这正是造成 使用@Accessors(chain = true)
后, EasyExcel解析不到数据的原因所在.
为什么使用了@Accessors(chain = true)
后, BeanMap
会拷贝不成功呢?
3、@Accessors注解
的作用#
使set方法返回的不是void, 而是当前对象
//不加 @Accessors(chain = true) 时
@Data
public class Student {
private String name;
}
// 等价于
public class Student {
private String name;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
// 加了 @Accessors(chain = true) 时
@Data
@Accessors(chain = true)
public class Student {
private String name;
}
// 等价于
public class Student {
private String name;
public String getName() {
return this.name;
}
public Student setName(String name) {
this.name = name;
return this;
}
}
4、解决方法#
可见, 需要使用BeanMap从Map拷贝到Bean, 需要Map 的Key与Bean的变量名一致, 并有对应的 set方法, 且set方法为 void, 才能拷贝成功。所以目前只能不使用这个注解即可解决该问题。
作者:YangRoc
出处:https://www.cnblogs.com/YangRoc/p/17186604.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了