需求:要将一张excel表格的数据批量导入数据库的user表中。
Excel:
user表结构:
实现:分两步
1、文件上传
SpringMVC中用的是MultipartFile对象作为参数传入。代码:
@RequestMapping(value = "test/upload",method = RequestMethod.POST)
public void excelToDatabase(@RequestParam("file") MultipartFile multipartFile)
{
if (multipartFile.isEmpty()) {
return "false";
}
System.out.println(multipartFile.getOriginalFilename());
}
使用POSTMAN测试文件上传:
Headers:
Key=Content-Type , Value=multipart/form-data
Body: form-data
Key:file,Value=该文件
发送结果:成功将文件名打印在控制台上
2、excel文件的解析与导入
这里用到一个java工具:jxl。可以参考这个https://www.cnblogs.com/xd502djj/archive/2011/08/15/2139394.html
其本质是先将excel文件拆成工作簿(叫Workbook),再将工作簿拆成工作表(Sheet),在工作表上使用getCell(column,row).getContents()方法就能够得到数据,为String类型,再进行转换,放入实体类中,写入数据库即可。
注意jxl操作的文件类型为file,所以上述步骤之前,还需要将multipartFile类型的excel文件转化成file,这里需要用到multipartFile.transferTo(file)方法。要注意这个方法没有返回值,也就是传入的file是输出的结果,所以我们需要先定义出一个空的file文件,方法为
File file = new File(getClass().getResource(".").getFile(), multipartFile.getOriginalFilename())
临时保存在项目路径下(获取当前路径的方法:getClass().getResource(".").getFile()),然后将multipartFile转换成它。
代码:
@RequestMapping(value = "/upload",method = RequestMethod.POST)
public String excelToDatabase(@RequestParam("file") MultipartFile multipartFile)
{
if(multipartFile.isEmpty()){
return "false";
}
int i = 1;// 提前定义列数,循环后可以打印出来,以查看成功导入的列数。
User user = new User();
try {
File file = new File(getClass().getResource(".").getFile().toString(), Objects.requireNonNull(multipartFile.getOriginalFilename()));
multipartFile.transferTo(file);
Workbook rwb = Workbook.getWorkbook(file);
Sheet rs = rwb.getSheet(0);
int columns = rs.getColumns();// 得到总列数
int rows = rs.getRows();// 得到总行数
if(!rs.getCell(0,0).getContents().equals("学号")) return "错误,第一列不是'学号'";
if(!rs.getCell(1,0).getContents().equals("姓名")) return "错误,第二列不是'姓名'";
if(!rs.getCell(2,0).getContents().equals("班级")) return "错误,第三列不是'班级'";
if(!rs.getCell(3,0).getContents().equals("学院")) return "错误,第四列不是'学院'";
if(!rs.getCell(4,0).getContents().equals("年级")) return "错误,第四列不是'年级'";
for (; i < rows; i++) {
for (int j = 0 ; j < columns; j++) {
user.setUsername(Long.parseLong(rs.getCell(j++, i).getContents()));
user.setName(rs.getCell(j++, i).getContents());
user.setClass_id(Integer.parseInt(rs.getCell(j++, i).getContents()));
user.setSchool(rs.getCell(j++, i).getContents());
user.setYear(rs.getCell(j++,i).getContents());
userService.newUser(user);
}
}
return "导入成功,总共添加"+(i-2)+"行记录,最后一行记录为[学号:"+user.getUsername()+",姓名:"+user.getName()+
",班级:"+user.getClass_id()+",学院:"+user.getSchool()+",年级:"+user.getYear()+"]";
} catch (IOException e) {
e.printStackTrace();
return "文件打开错误";
} catch (Exception e) {
e.printStackTrace();
return "导入失败,存在重复的学号或数据格式错误,导入终止。成功添加"+(i-1)+"行记录,错误的记录为:[学号:"+user.getUsername()+
",姓名:"+user.getName()+",班级:"+user.getClass_id()+",学院:"+user.getSchool()+",年级:"+user.getYear()+"]";
}
}
导入结果:
导入成功时,Controller返回结果:
导入失败时,比如有重复数据时:(username为唯一主键,当有重复数据时mysql会抛出Exception异常,catch这个异常即可)