做个笔记记录一下前段时间项目中学到的内容,利用EasyExcel将Excel中的数据导入到数据库中。
若需要官方文件请见 https://alibaba-easyexcel.github.io/quickstart/read.html
Excel表:
数据库表
表名为edu_subject
在edu_subject表中记录了课程的相关信息,其中id、gmt_create、gmt_modified字段由Mybatis-plus自动生成,sort字段默认为0,title字段记录课程名称,若该字段中某条记录为Excel表中的一级分类,就将parent_id字段设置为0,表示没有父类;若该字段中某条记录为Excel表中的二级分类,就将该记录的parent_id字段设置为数据库中对应的一级分类的id值。
Excel表对应实体类
做一些前期准备工作,首先应该设置数据信息对应的实例类,为EduSubject类,还应该设置Excel表中数据对应的实体类,因为EasyExcel会Excel中数据一行一行进行读取,并将数据封装在实体类中
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
@Data public class SubjectData { @ExcelProperty(index=0) //表示对应Excel表中第一列,也就是一级分类 private String oneSubjectName; @ExcelProperty(index=1) private String twoSubjectName; }
Service层
service层代码是由Mybatis-plus自动生成,这里直接重写saveSubject方法,实现需求。
通过调用EasyExcel的read方法实现对Excel文件的读取,该方法需要三个参数,分别是文件输入流,Excel表对应的实体类和监听器对象(业务具体代码由监听器实现)。由于每次调用该方法都需要重新new一个对象,所以无法交给spring托管,所以我们需要在controller层将service类传递到该方法*监听器使用。
import com.alibaba.excel.EasyExcel;
import com.atzjhydx.eduservice.entity.EduSubject;
import com.atzjhydx.eduservice.entity.excel.SubjectData;
import com.atzjhydx.eduservice.listener.SubjectExcelListener;
import com.atzjhydx.eduservice.mapper.EduSubjectMapper;
import com.atzjhydx.eduservice.service.EduSubjectService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.InputStream;
@Service public class EduSubjectServiceImpl extends ServiceImpl<EduSubjectMapper, EduSubject> implements EduSubjectService { @Override public void saveSubject(MultipartFile file,EduSubjectService eduSubjectService) { try { //文件输入流 InputStream in = file.getInputStream(); //调用方法进行读取 EasyExcel.read(in,SubjectData.class,new SubjectExcelListener(eduSubjectService)).sheet().doRead(); }catch (Exception e){ e.printStackTrace(); } } }
监听器
import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.event.AnalysisEventListener; import com.atzjhydx.eduservice.entity.EduSubject; import com.atzjhydx.eduservice.entity.excel.SubjectData; import com.atzjhydx.eduservice.service.EduSubjectService; import com.atzjhydx.servicebase.enums.CustomizeErrorCode; import com.atzjhydx.servicebase.exceptionhandler.CustomizeException; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; public class SubjectExcelListener extends AnalysisEventListener<SubjectData> { //因为SubjectExcelListener不能交给spring进行管理,需要自己new,不能注入其他对象 //不能实现数据库操作(通过在controller层调用service时将subject的service层传递进来) public EduSubjectService subjectService; public SubjectExcelListener(EduSubjectService subjectService) { this.subjectService = subjectService; } public SubjectExcelListener() { } //读取excel内容,一行一行读取,会将每行的数据封装到SubjectData中 @Override public void invoke(SubjectData subjectData, AnalysisContext analysisContext) { if (subjectData == null) { throw new CustomizeException(CustomizeErrorCode.DATA_NOT_FOUND); } //一行一行读取,每次读取有两个值,第一个值一级分类,第二个值二级分类 //判断一级分类是否重复 EduSubject existOneSubject = this.existOneSubject(subjectService, subjectData.getOneSubjectName()); if (existOneSubject == null){ //没有相同的一级分类,进行添加 existOneSubject = new EduSubject(); existOneSubject.setParentId("0"); existOneSubject.setTitle(subjectData.getOneSubjectName());//设置一级分类名称 subjectService.save(existOneSubject); //MP会自动为existOneSubject其他属性添加值 } //获取一级分类的id值 String pid = existOneSubject.getId(); //添加二级分类 //判断二级分类是否重复 EduSubject existTwoSubject = this.existTwoSubject(subjectService, subjectData.getTwoSubjectName(), pid); if (existTwoSubject == null){ existTwoSubject = new EduSubject(); existTwoSubject.setParentId(pid); existTwoSubject.setTitle(subjectData.getTwoSubjectName()); subjectService.save(existTwoSubject); } } /** * 通过title获取一级分类(用于判断是否有重复的一级分类) * @param eduSubjectService * @param name 一级分类名称 * @return 传入的一级分类名称在数据库中对应信息的实体类 */ private EduSubject existOneSubject(EduSubjectService eduSubjectService, String name) { QueryWrapper<EduSubject> wrapper = new QueryWrapper<>(); wrapper.eq("title", name); wrapper.eq("parent_id", "0"); EduSubject oneSubject = eduSubjectService.getOne(wrapper); return oneSubject; } /** * 通过title获取二级分类(用于判断是否有重复的二级分类) * @param eduSubjectService * @param name 二级分类名称 * @param pid 一级分类名称在数据库中对应的id属性值 * @return 传入的二级分类名称在数据库中对应信息的实体类 */ private EduSubject existTwoSubject(EduSubjectService eduSubjectService, String name, String pid){ QueryWrapper<EduSubject> wrapper = new QueryWrapper<>(); wrapper.eq("title",name); wrapper.eq("parent_id",pid); EduSubject twoSubject = subjectService.getOne(wrapper); return twoSubject; } @Override public void doAfterAllAnalysed(AnalysisContext analysisContext) { } }
Controller层
import com.atzjhydx.commonutils.R;
import com.atzjhydx.eduservice.service.EduSubjectService;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
@RestController @RequestMapping("/eduservice/edu-subject") @CrossOrigin @Api(value = "课程管理") public class EduSubjectController { @Autowired private EduSubjectService subjectService; //添加课程分类 //获取上传过来的文件 @PostMapping("addSubject") public R addSubject(MultipartFile file){ //上传过来excel文件 subjectService.saveSubject(file,subjectService); return R.ok(); } }