使用EasyExcel实现excel导入
下文将简述在SpringBoot如何使用EasyExcel,从多sheet页,上万级数据excel导入到数据库中,本文使用mybatis作为ORM映射框架
准备环境
创建用户表users
创建用户实体对象级底层方法
userMapper.xml中定义批量增加方法
<insert id="batchSave" parameterType="java.util.List">
insert into users(user_name,password,age,email,auth)
values
<foreach collection="userVoList" item="item" index="id" separator=",">
(#{item.userName},#{item.password},#{item.age},#{item.email},#{item.auth})
</foreach>
</insert>
其他业务方法不在赘述,下面开始使用EasyExcel
官方文档
1.引入依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.3.2</version>
</dependency>
2.准备一个待导入的excel
2.定义一个excel列名和实体的映射类
ExcelProperty 用于指定列名,此处也可以使用index指定列;
还可以使用 @NumberFormat进行数字格式化如:
保留两位小数@NumberFormat(“#.##%”)
使用 @DateTimeFormat进行日期格式化如:
@DateTimeFormat(“yyyy-MM-dd”)
@Data
public class ConverterData {
private Integer id;
@ExcelProperty("名称")
private String userName;
@ExcelProperty("密码")
private String password;
/**
* 年龄
*/
@ExcelProperty("年龄")
private Integer age;
/**
* email
*/
@ExcelProperty("邮箱地址")
private String email;
/**
* 权限
*/
@ExcelProperty("权限")
private String auth;
}
2.定义一个监听器ReadListener
@Slf4j
public class UserListener implements ReadListener<ConverterData> {
private static final int BATCH_COUNT=100;//定义批量处理的条数
private List<UserVo> cacheDataList= ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);//用于缓存解析的数据
UserService userService;
public UserListener(){
userService=new UserServiceImpl();
}
public UserListener(UserService userService){
this.userService=userService;
}
@Override
public void onException(Exception exception, AnalysisContext context) throws Exception {
ReadListener.super.onException(exception, context);
}
@Override
public void invokeHead(Map<Integer, ReadCellData<?>> headMap, AnalysisContext context) {
ReadListener.super.invokeHead(headMap, context);
}
@Override
public void extra(CellExtra extra, AnalysisContext context) {
ReadListener.super.extra(extra, context);
}
@Override
public boolean hasNext(AnalysisContext context) {
return ReadListener.super.hasNext(context);
}
/**
* 每一条数据都会调用,当集合的大小等于定义的批量处理大小就会保存到数据库
* @param converterData excel映射对象
* @param analysisContext
*/
@Override
public void invoke(ConverterData converterData, AnalysisContext analysisContext) {
log.info("解析到数据:"+new Gson().toJson(converterData));
String userName= converterData.getUserName();
String password=converterData.getPassword();
if(StringUtil.isNullOrEmpty(userName)||StringUtil.isNullOrEmpty(password)){
return;
}
//转换成实体类
UserVo userVo = new UserVo();
BeanUtils.copyProperties(converterData,userVo);
cacheDataList.add(userVo);
if(cacheDataList.size()>=BATCH_COUNT){//
saveData();
cacheDataList=ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
}
}
/**
* 所有数据解析完成了 都会来调用,遗留的数据
* @param analysisContext
*/
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
saveData();
}
/**
* 保存数据
*/
private void saveData(){
log.info(cacheDataList.size()+"条数据开始存储数据库");
userService.batchSave(cacheDataList);
log.info("保存成功");
}
}
3.导入单个sheet页的excel,直接在Test中测试.数据行804
String filePath="D:\\workspace"+ File.separator+"1.xlsx";
long pre= System.currentTimeMillis();
EasyExcel.read(filePath, ConverterData.class,new UserListener(userService)).sheet().doRead();
long now = System.currentTimeMillis();
System.out.println("导入耗时"+(now-pre)+"ms");
测试结果804行数据,花费844ms
4.导入多个sheet页数据,先获取sheet页在执行导入操作
导入前数据条数:
ExcelReader excelReader = EasyExcel.read(filePath).build();
ExcelReadExecutor excelReadExecutor = excelReader.excelExecutor();
List<ReadSheet> readSheets = excelReadExecutor.sheetList();
UserListener userListener = new UserListener(userService);
for(ReadSheet sheet:readSheets){
ReadSheet sheet1 = EasyExcel.readSheet(sheet.getSheetNo()).head(ConverterData.class).registerReadListener(userListener).build();
excelReader.read(sheet1);
}
10个sheet,1w+数据
以上内容来自easyExcel官网,更多内容请查看官网