Vue前端上傳EXCEL文件,後端(springBoot+MyBatis+MySQL)解析EXCEL並批量插入/更新數據庫

Vue前端

前端主要用了element-ui的upload組件。

      <el-upload
        class="filter-item"
        name="excelFile"
        :action="uploadUrl()"
        :on-error="uploadFalse"
        :on-success="uploadSuccess"
        :before-upload="beforeAvatarUpload"
        :limit="1"
         accept=".xlsx,.xls"
        :show-file-list="false"
        :file-list="fileList">
         <el-button  style="margin-left: 10px;" icon="el-icon-edit" type="primary">批量上架</el-button>
       </el-upload>

關於每個字段的意思:

uploadUrl() 是後臺接口(接受上傳的文件並做後端的邏輯處理) 注意:uploadUrl方法中,直接return的是你的後端URL接口,可以是相對路徑,也可以是絕對路徑。

upLoadData是上傳文件時要上傳的額外參數,也可以不寫,將參數直接帶在URL請求中
形似: url + “?businessName=” + this.businessName

uploadError是上傳文件失敗時的回掉函數
uploadSuccess是文件上傳成功時的回掉函數

beforeAvatarUpload是在上傳文件之前調用的函數,可以在這裏進行文件類型的判斷,對上傳格式及大小作限制

**:auto-upload=“false”**是停止文件自動上傳模式

**name=“excelFile”**這裏是將導入的EXCEL文件命名,並傳給後端,所以後端接口的入參也要是這個名字,下面會貼代碼。

:file-list=“fileList” 顯示已上傳的文件列表

 uploadSuccess(response, file, fileList) {
      console.log(response)
      if (response.code==200) {
        this.$message({
          message: response.message,
          type: 'success'
        });
      } else {
        this.$message({
          message: response.message,
          type: 'error'
        });
      }
    },
    uploadFalse(response, file, fileList) {
      this.$message({
          message: '文件上傳失敗!',
          type: 'error'
        });
    },
    // 上傳前對文件的大小的判斷
    beforeAvatarUpload(file) {
      const extension = file.name.split(".")[1] === "xls";
      const extension2 = file.name.split(".")[1] === "xlsx";
      const isLt2M = file.size / 1024 / 1024 < 10;
         if (!extension && !extension2) {
           this.$message({
            message: '上傳模板只能是 xls、xlsx格式!',
            type: 'error'
           });
          }
          if (!isLt2M) {
           console.log("上傳模板大小不能超過 10MB!");
           this.$message({
            message: '上傳模板大小不能超過 10MB!',
            type: 'error'
          });
         }
        return extension || extension2 || extension3 || (extension4 && isLt2M);
    },
    uploadUrl: function() {
      return (
        process.env.VUE_APP_BASE_API+'/good/ExcelInsertGoodinStore'+
        "?businessid=" +
        this.$store.getters.id
      );
    },

後端

controller層

  @RequestMapping(value = "/ExcelInsertGoodinStore", method = RequestMethod.POST)
    @ResponseBody
    public RetResult ExcelInsertGoodinStore(@RequestParam("excelFile") MultipartFile excelFile,
                                           @RequestParam(value = "businessid", required = true ) int businessid) {
        String name = excelFile.getOriginalFilename();
        try {
            if(goodService.excelToList(excelFile.getInputStream(),businessid)>0) {
                return new RetResult().setCode(RetCode.SUCCESS).setMessage("導入Excel批量添加商品成功!");
            }else return new RetResult().setCode(RetCode.FAIL).setMessage("導入Excel批量添加商品失敗!");
        } catch (Exception e) {
            e.printStackTrace();
            return new RetResult().setCode(RetCode.FAIL).setMessage("文件內容出現錯誤,導致無法正確導入");
        }
    }

service層:如何解析Excel文件

 public int  excelToList(InputStream inputStream,int businessid) throws IOException, InvalidFormatException {
        List<GoodinStore> gisList=new ArrayList<GoodinStore>();
        Workbook workbook = null;
        workbook = WorkbookFactory.create(inputStream);
        inputStream.close();
        //工作表對象
        Sheet sheet = workbook.getSheetAt(0);
        //總行數
        int rowLength = sheet.getLastRowNum() + 1;
        //工作表的列
        Row row = sheet.getRow(0);
        //總列數
        int colLength = row.getLastCellNum();
        for (int i = 1; i < rowLength; i++) {
            row = sheet.getRow(i);
            row.getCell(0).setCellType(CellType.STRING);
            String cell0 = row.getCell(0).getStringCellValue().trim();
            GoodinStore gis=new GoodinStore();
            .....
            gisList.add(gis);
            }
        }
        return goodMapper.insertMultiGis(gisList);
    }

注意:
使用了getStringCellValue()方法來獲取值,POI會判斷單元格的類型,如果非字符串類型就會拋出異常。

Exception in thread “main” java.lang.IllegalStateException: Cannot get a STRING value from a NUMERIC cell

解決方法是在讀取某單元格時,使用setCellType()方法先將該單元格的類型設置爲STRING。

row.getCell(0).setCellType(CellType.STRING);

MyBatis:實現批量插入

利用唯一索引和ON DUPLICATE KEY UPDATE實現重複覆蓋、不重複插入的操作

<!--批量添加上架商品-->
    <insert id="insertMultiGis" parameterType="java.util.List"  useGeneratedKeys="true" keyProperty="gis_id" keyColumn="gis_id">
        INSERT INTO goodinstore
        (goodid,businessid,retailprice,min_stock,stock)
        values
        <foreach collection="list" item="item" index="index" separator=",">
         (#{item.good.id},#{item.businessid},#{item.retailPrice},#{item.min_stock},#{item.stock})
        </foreach>
        ON DUPLICATE KEY UPDATE
        retailprice = values(retailprice),
        min_stock = values(min_stock),
        stock = values(stock)
    </insert>

注意:useGeneratedKeys=“true” keyProperty=“gis_id” keyColumn="gis_id"實現主鍵自增

在mysql中設置唯一索引Unique Index

UNIQUE KEY的用途:主要是用來防止數據插入的時候重複的。
1,創建表時 CREATE TABLE Persons ( Id_P int NOT NULL, LastName
varchar(255) NOT NULL, FirstName varchar(255), Address varchar(255),
City varchar(255), UNIQUE (Id_P) ) 如果需要命名 UNIQUE 約束,以及爲多個列定義 UNIQUE
約束,請使用下面的 SQL 語法: CREATE TABLE Persons ( Id_P int NOT NULL,
LastName varchar(255) NOT NULL, FirstName varchar(255), Address
varchar(255), City varchar(255), CONSTRAINT uc_PersonID UNIQUE
(Id_P,LastName) )

2,當表已被創建時,如需在 “Id_P” 列創建 UNIQUE 約束,請使用下列 SQL:
ALTER TABLE Persons ADD UNIQUE (Id_P)
如需命名 UNIQUE 約束,並定義多個列的 UNIQUE 約束,請使用下面的 SQL 語法:
ALTER TABLE Persons ADD CONSTRAINT uc_PersonID UNIQUE (Id_P,LastName)

3,撤銷 UNIQUE 約束

如需撤銷 UNIQUE 約束,請使用下面的 SQL: MySQL:

ALTER TABLE Persons DROP INDEX uc_PersonID

MySQL中的insert ignore into, replace into等的一些用法總結

1.insert ignore into

當插入數據時,如出現錯誤時,如重複數據,將不返回錯誤,只以警告形式返回。所以使用ignore請確保語句本身沒有問題,否則也會被忽略掉。例如:
INSERT IGNORE INTO books (name) VALUES (‘MySQL Manual’) INSERT IGNORE INTO books (name) VALUES (‘MySQL Manual’),(‘NGINX Manual’),(‘REDIS Manual’)

2.on duplicate key update 當primary或者unique重複時,則執行update語句,如update後爲無用語句,如id=id,則同1功能相同,但錯誤不會被忽略掉。例如,爲了實現name重複的數據插入不報錯:
INSERT INTO books (name) VALUES (‘MySQL Manual’) ON duplicate KEY UPDATE id = id

3.insert … select … where not exist 根據select的條件判斷是否插入,可以不光通過primary 和unique來判斷,也可通過其它條件。例如:
INSERT INTO books (name) SELECT ‘MySQL Manual’ FROM dual WHERE NOT EXISTS (SELECT id FROM books WHERE id = 1)

4.replace into 如果存在primary or unique相同的記錄,則先刪除掉。再插入新記錄。注意若原記錄存在(a1,b1,c1),新記錄爲(a1,b2),則replace後c字段爲null
REPLACE INTO books SELECT 1, ‘MySQL Manual’ FROM books

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章