关于使用easyExceld读取前端文件和MybatisPlus批量插入
文章目录
- 关于使用easyExceld读取前端文件和MybatisPlus批量插入
- 实体类
- 监听器
- 开始调用
- 可能出现的问题
- 最后,关于MybatisPlus的批量插入
- 写一个工具类
- 写一个配置类
- 到Mappe中添加这个方法
最近写项目,后端需要用到easyExcel来获取前端上传的表格,分析表格数据并存储到数据库
项目暂时是:springBoot + MybatisPlus
easyExcel官方文档地址:读Excel | Easy Excel (alibaba.com)
因为项目中我暂时只用到读Excel,所以文档的地址就给大家放到上面啦,有其他需要的话可以自查
实体类
第一步,你需要一个实体类,这个实体类对应数据库中的一个表
然后使用@ExcelProperty注解将excel表的列名对应的属性绑定起来
比如:我的Excel表是这样的:
那么绑定到实体类就应该是这样的:
@Data
public class Classroom implements Serializable {
//自增
private int classroomId;
@ExcelProperty("教室号")
private String classroomName;
//管理员的buildingId
private int buildingId;
@ExcelProperty("摄像头设备id")
private String cameraId;
@ExcelProperty("esp8266id")
private String espId;
@ExcelProperty("可通电的最少人数")
private int numLimitOn;
@ExcelProperty("教室分流人数阈值")
private int numPeakFlow;
@ExcelProperty("可通电的最低温度")
private float temperatureLimitOn;
@ExcelProperty("断电最高温度阈值")
private float temperatureLimitOff;
@ExcelProperty("教室容量")
private int classroomCapacity;
@ExcelProperty("是否特殊供电")
private int specialOn;
}
监听器
第二步,按照官方文档,还需要一个监听器
//官方文档中又有比较详细的注释,我的代码因为要实现自己的需求,所以和官方文档可能不太一样
//这里我就挑一些可能比较重要的部分写上注释
@Data
@Component //加上Component注解的同时记得到启动类上使用@MapperScan加上这个类的包路径,不然扫描不到会报空指针异常
public class ClassroomListener extends AnalysisEventListener<Classroom> {
private static final int BATCH_COUNT = 10000;
private static List<Classroom> cachedDataList = new ArrayList<>();
private int buildingId;
@Resource
private ClassroomMapper classroomMapper;
//这是一个回调函数,就是每读取一条数据都会来执行这个方法
@Override
public void invoke(Classroom classroom, AnalysisContext analysisContext) {
classroom.setBuildingId(buildingId);
//每次读取excel表中的一条数据,都存放到list中
cachedDataList.add(classroom);
//直到超过10000条,就进行持久化操作,然后清空ilst集合,继续读取
if(cachedDataList.size() >= BATCH_COUNT){
saveData();
cachedDataList.clear();
}
}
//这个函数是只有在读取完所有数据之后,才会调用(只执行一次)
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
saveData();
cachedDataList.clear();
}
//这里是持久化操作,因为不想多次调用insert,所以我选择批量插入
//insertBatchSomeColumn:这个批量插入还需要做其他的配置,放在后面将
private void saveData() {
//批量插入
classroomMapper.insertBatchSomeColumn(cachedDataList);
}
}
开始调用
到这一步就可以开始通过这个监听器来读写excel了
//注入listener
@Resource
ClassroomListener classroomListener;
pubilc void test(){
//是的,在你的业务层调用easyExcel读写excel的时候只需要这一行代码就够了
//你可以配合上你自己的代码逻辑去使用
EasyExcel.read(multipartFile.getInputStream(), Classroom.class, classroomListener)
.sheet().doRead();
}
可能出现的问题
如果有仔细看easyExcel官方文档中的代码的同学可能就会,发现,我的代码和官方的其实还是有细微的差别
区别就在于,我通过@Compotent注解手动的将Listener作为一个普通组件交给Spring,从而做到可以在Listener中注入Mapper
而官方文档中的是没有将他交给Spring的,而且在测试的时候,官方代码如下:
EasyExcel.read(multipartFile.getInputStream(), Classroom.class, new ClassroomListener()).sheet().doRead();
仔细看,可以发现官方文档在业务层的代码中的Listen是直接通过new新建出来的
而我的是则是直接在业务层注入Listen这个Bean(上面有提到我给Listener加了@Component注解,已经把他交给Spring了)
因为事实上,监听器,过滤器,以及拦截器都是不归Spring管的
所以如果你不将监听器手动交给Spring的,直接在监听器中使用@Resource注解的话,就会报空指针异常,因为这个时候注入是无效的
感兴趣的可以上网搜一下:”监听器中@Resource注解和@Autowire注解失效“
当然,解决这个问题也不止可以用注解,也可以自己写工具类,提供一些其他的方法去拿到Bean
最后,关于MybatisPlus的批量插入
MybatisPlus其实也有提供一个批量插入的方法,但是那个方式本质上也是多次的调用insert()
关于insertBatchSomeColumn(List list)这个方法,大家可以直接复制下面的代码就可以了
写一个工具类
package com.airweb.util;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import com.baomidou.mybatisplus.extension.injector.methods.InsertBatchSomeColumn;
import java.util.List;
public class InsertBatchSqlInjector extends DefaultSqlInjector {
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
List<AbstractMethod> methodList = super.getMethodList(mapperClass);
methodList.add(new InsertBatchSomeColumn());
return methodList;
}
}
写一个配置类
package com.airweb.config;
import com.airweb.util.InsertBatchSqlInjector;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
@Component
public class MybatisPlusConfig {
@Bean
public InsertBatchSqlInjector easySqlInjector () {
return new InsertBatchSqlInjector();
}
}
到Mappe中添加这个方法
package com.airweb.mapper;
import com.airweb.model.entity.Building;
import com.airweb.model.entity.Classroom;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface ClassroomMapper extends BaseMapper<Classroom> {
/**
* 批量插入
* @param classrooms
*/
void insertBatchSomeColumn(@Param("list") List<Classroom> classrooms);
}