up:: Excel的解析与处理
说明: 本篇博客开始正式开发Excel在项目中的功能
开发批量上传接口controller层
1. 打开ProductAdminController.java文件,添加接口
@ApiOperation("后台批量上传商品接口")
@PostMapping("/admin/upload/product")
public ApiRestResponse uploadProduct(@RequestParam("file") MultipartFile multipartFile) throws IOException {
}
说明: 此处是上传文件,所以使用file接收
接下来老生常谈,添加sevice的接口以及实现
void addProductByExcel(File destFile) throws IOException;
2. 开发service层,实现批量上传
1. 首先添加POI的依赖
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.16</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.16</version>
</dependency>
2.需要额外开发一个列表将excel中的内容一一读取出来(核心重点!)
private List<Product> readProductsFromExcel(File excelFile) throws IOException {
ArrayList<Product> listProducts = new ArrayList<>();
FileInputStream inputStream = new FileInputStream(excelFile);
XSSFWorkbook workbook = new XSSFWorkbook(inputStream);
XSSFSheet firstSheet = workbook.getSheetAt(0);
Iterator<Row> iterator = firstSheet.iterator();
while (iterator.hasNext()) {
Row nextRow = iterator.next();
Iterator<Cell> cellIterator = nextRow.cellIterator();
Product aProduct = new Product();
while (cellIterator.hasNext()) {
Cell nextCell = cellIterator.next();
int columnIndex = nextCell.getColumnIndex();
switch (columnIndex) {
case 0:
aProduct.setName((String) ExcelUtil.getCellValue(nextCell));
break;
case 1:
aProduct.setImage((String) ExcelUtil.getCellValue(nextCell));
break;
case 2:
aProduct.setDetail((String) ExcelUtil.getCellValue(nextCell));
break;
case 3:
Double cellValue = (Double) ExcelUtil.getCellValue(nextCell);
aProduct.setCategoryId(cellValue.intValue());
break;
case 4:
cellValue = (Double) ExcelUtil.getCellValue(nextCell);
aProduct.setPrice(cellValue.intValue());
break;
case 5:
cellValue = (Double) ExcelUtil.getCellValue(nextCell);
aProduct.setStock(cellValue.intValue());
break;
case 6:
cellValue = (Double) ExcelUtil.getCellValue(nextCell);
aProduct.setStatus(cellValue.intValue());
break;
default:
break;
}
}
listProducts.add(aProduct);
}
workbook.close();
inputStream.close();
return listProducts;
}
说明:
这里需要注意,case的分类情况不是乱写的,而是按照数据库的顺序来写,因为excel表内内容导入后最终都要存到数据库,那么excel里的每一列内容的数据类型等等都要和数据库字段保持一致!!!!
这里只从name到status字段,按照顺序写下来的,id之所以没写,因为是自增主键,可以自动生成。。。?
ExcelUtil工具类:
Utils包下新建ExcelUtil.java文件
package com.imooc.mall.util;
import org.apache.poi.ss.usermodel.Cell;
/**
* 描述: 处理Excel
*/public class ExcelUtil {
public static Object getCellValue(Cell cell) {
switch (cell.getCellTypeEnum()) {
case STRING:
return cell.getStringCellValue();
case BOOLEAN:
return cell.getBooleanCellValue();
case NUMERIC:
return cell.getNumericCellValue();
}
return null;
}
}
说明:
cell.getCellTypeEnum() 表示对类型的枚举
3.正式开发service层
@Override
public void addProductByExcel(File destFile) throws IOException {
List<Product> products = readProductsFromExcel(destFile);
for (int i = 0; i < products.size(); i++) {
Product product = products.get(i);
Product productOld = productMapper.selectByName(product.getName());
if (productOld != null) {
throw new ImoocMallException(ImoocMallExceptionEnum.NAME_EXISTED);
}
int count = productMapper.insertSelective(product);
if (count == 0) {
throw new ImoocMallException(ImoocMallExceptionEnum.CREATE_FAILED);
}
}
}
说明:
参考下这篇博客,关于insertSelective与insert的区别: insertSelective和insert的区别?_oldguncm的博客-CSDN博客
[!摘要] 1、selective的意思是:选择性 2、insertSelective—选择性保存数据; 比如User里面有三个字段:id,name,age,password 但是我只设置了一个字段; User u=new user(); u.setName(“张三”); insertSelective(u); 3、insertSelective执行对应的sql语句的时候,只插入对应的name字段;(主键是自动添加的,默认插入为空) insert into tb_user (id,name) value (null,“张三”); 4、而insert则是不论你设置多少个字段,统一都要添加一遍,不论你设置几个字段,即使是一个。 User u=new user(); u.setName(“张三”); insertSelective(u);
其中也提到主键是自动添加的。。。
insertSelective的返回值: insertselective返回主键ID_张名佳的博客-CSDN博客_insertselective返回主键
只会返回0和1,1代表插入成功,0代表插入失败。所以说凡是数据库里的更新操作(insert/update/delete)的返回值不是0就是1嘞?看来数据库没学好。。。需要回炉重造。。。
测试
1. 打开postman,如何传输excel文件
2.选择我们的excel表
excel表: