做个笔记记录一下前段时间项目中学到的内容,利用EasyExcel将Excel中的数据导入到数据库中。
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;
@Datapublic classSubjectData {
@ExcelProperty(index=0) //表示对应Excel表中第一列,也就是一级分类
privateString oneSubjectName;
@ExcelProperty(index=1)privateString 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;
@Servicepublic class EduSubjectServiceImpl extends ServiceImpl implementsEduSubjectService {
@Overridepublic voidsaveSubject(MultipartFile file,EduSubjectService eduSubjectService) {try{//文件输入流
InputStream in =file.getInputStream();//调用方法进行读取,监听器代码在下面
EasyExcel.read(in,SubjectData.class,newSubjectExcelListener(eduSubjectService)).sheet().doRead();
}catch(Exception e){
e.printStackTrace();
}
}
}
监听器
importcom.alibaba.excel.context.AnalysisContext;importcom.alibaba.excel.event.AnalysisEventListener;importcom.atzjhydx.eduservice.entity.EduSubject;importcom.atzjhydx.eduservice.entity.excel.SubjectData;importcom.atzjhydx.eduservice.service.EduSubjectService;importcom.atzjhydx.servicebase.enums.CustomizeErrorCode;importcom.atzjhydx.servicebase.exceptionhandler.CustomizeException;importcom.baomidou.mybatisplus.core.conditions.query.QueryWrapper;public class SubjectExcelListener extends AnalysisEventListener{//因为SubjectExcelListener不能交给spring进行管理,需要自己new,不能注入其他对象//不能实现数据库操作(通过在controller层调用service时将subject的service层传递进来)
publicEduSubjectService subjectService;publicSubjectExcelListener(EduSubjectService subjectService) {this.subjectService =subjectService;
}publicSubjectExcelListener() {
}//读取excel内容,一行一行读取,会将每行的数据封装到SubjectData中
@Overridepublic voidinvoke(SubjectData subjectData, AnalysisContext analysisContext) {if (subjectData == null) {throw newCustomizeException(CustomizeErrorCode.DATA_NOT_FOUND);
}//一行一行读取,每次读取有两个值,第一个值一级分类,第二个值二级分类//判断一级分类是否重复
EduSubject existOneSubject = this.existOneSubject(subjectService, subjectData.getOneSubjectName());if (existOneSubject == null){ //没有相同的一级分类,进行添加
existOneSubject = newEduSubject();
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= newEduSubject();
existTwoSubject.setParentId(pid);
existTwoSubject.setTitle(subjectData.getTwoSubjectName());
subjectService.save(existTwoSubject);
}
}/*** 通过title获取一级分类(用于判断是否有重复的一级分类)
*@parameduSubjectService
*@paramname 一级分类名称
*@return传入的一级分类名称在数据库中对应信息的实体类*/
privateEduSubject existOneSubject(EduSubjectService eduSubjectService, String name) {
QueryWrapper wrapper = new QueryWrapper<>();
wrapper.eq("title", name);
wrapper.eq("parent_id", "0");
EduSubject oneSubject=eduSubjectService.getOne(wrapper);returnoneSubject;
}
/*** 通过title获取二级分类(用于判断是否有重复的二级分类)
*@parameduSubjectService
*@paramname 二级分类名称
*@parampid 一级分类名称在数据库中对应的id属性值
*@return传入的二级分类名称在数据库中对应信息的实体类*/
privateEduSubject existTwoSubject(EduSubjectService eduSubjectService, String name, String pid){
QueryWrapper wrapper = new QueryWrapper<>();
wrapper.eq("title",name);
wrapper.eq("parent_id",pid);
EduSubject twoSubject=subjectService.getOne(wrapper);returntwoSubject;
}
@Overridepublic voiddoAfterAllAnalysed(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 classEduSubjectController {
@AutowiredprivateEduSubjectService subjectService;//添加课程分类//获取上传过来的文件
@PostMapping("addSubject")publicR addSubject(MultipartFile file){//上传过来excel文件
subjectService.saveSubject(file,subjectService);returnR.ok();
}
}