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表:

3.批量导入成功