Excel大数据量上传导入系统,mybatis写法及程序实现

  背景:
     根据项目需求,一次性将10万条Excel数据插入数据库中,如果使用传统的poi解析Excel然后执行10万次insert语句,整个导入过程将非常耗时,poi解析数据非常耗内存,在实际生产环境中使用也会报错等等。
    所以分两步优化,解析Excel使用阿里巴巴项目组提供了easyexcel工具类(注意:读取文件务必使用2.0.5+版本,其他版本可能会有bug),将Excel解析成list,10万条数据解析大概8秒左右。数据库层使用mybatis的foreach标签将大数据量分隔为每500条批量插入一次数据库,优化后插入数据库效率明显提升。

  

1、controller

@RequestMapping("importData")
public ReturnData importData(@RequestParam("file") MultipartFile file) {
    logger.info("上传excel文件名称:",file.getOriginalFilename());
    ReturnData returnData;
    try {
        returnData = importDataService.importData(file);
    } catch (Exception e) {
        e.printStackTrace();
        returnData = new ReturnData(0, null, "Excel导入数据异常!");
    }
    return returnData;
}

2、service

/**
 * 上传Excel文件
 * @param file
 * @return
 */
@Override
public ReturnData importData(MultipartFile file) {
    if (file == null) {
        return new ReturnData(0, null, "上传文件为空!");
    }
    List importDataVoList;
    InputStream inputStream = null;
    try {
        inputStream = file.getInputStream();
        String originalFilename = file.getOriginalFilename();
        String suffix = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
        if (!"xls".equals(suffix) && !"xlsx".equals(suffix)) {
            return new ReturnData(0, null, "请上传Excel格式的文件");
        }
        importDataVoList = ExcelUtil.readExcelWithModel(inputStream, ImportDataVo.class,suffix);
        if(importDataVoList.size() <= 0){
            return new ReturnData(0,null,"Excel中没有可上传的数据");
        }
        List importDatalist = new ArrayList<>();
        for (Object importDataVo : importDataVoList) {
            ImportData importData = new ImportData();
            BeanUtils.copyProperties(importDataVo , importData );
            importDatalist.add(importData);
        }
        //批量插入数据
        int rows = 0;
        try {
            rows = batchInsertData(importDatalist); //切割list插入数据库
            logger.info("导入成功,共插入:" + rows + "条数据!");
        }catch (Exception e){
            e.printStackTrace();
        }
        return new ReturnData(1,rows,"success");
    } catch (Exception e){
        e.printStackTrace();
        logger.info("导入数据异常!");
        return new ReturnData(1,null,"导入数据异常");
    }
}
//分隔为每500条批量入库
private int batchInsertData(List importDatalist) {
    int rows = 0;
    for (int i = 0; i < importDatalist.size()/500 + 1 ; i++) {
        int end = (i+1)* 500;
        if(end >= importDatalist.size()){
            end = importDatalist.size();
        }
        List importDatas = importDatalist.subList(i*500,end);
        int flag = importDataMapper.batchInsertOrUpdateList(importDatas);
        if(flag > 0 ){
            rows = rows + end-(i*500);
        }
    }
    return rows;
}

3、mybatis的xml文件

注意:insert语句后的ON DUPLICATE KEY UPDATE 子句,表示如果插入的行与表中现有数据的唯一索引或者主键重复的话,则会更新该条数据;如果插入的行与表中现有数据的唯一索引或者主键不重复,则执行新记录插入操作。


    
          SELECT LAST_INSERT_ID()
    
       insert into import_data
        (user_num, user_name, IDcard,
         age, gender,address,native_place,phone)
        values
         
            (
             #{importData.userNum},
             #{importData.userName},
             #{importData.idcard},
             #{importData.age},
             #{importData.gender},
             #{importData.address},
             #{importData.nativePlace},
             #{importData.phone}
            )
        
        ON DUPLICATE KEY UPDATE
        user_num= VALUES(user_num),
        user_name= VALUES(user_name),
        IDcard= VALUES(IDcard),
        age= VALUES(age),
        gender= VALUES(gender),
        address= VALUES(address),
        native_place= VALUES(native_place),
        phone= VALUES(phone)
 

 

你可能感兴趣的:(Excel大数据量上传导入系统,mybatis写法及程序实现)