ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

基于EasyExcel的大数据量导入并去重

2022-07-24 21:04:42  阅读:180  来源: 互联网

标签:antia1 demo EasyExcel 导入 数据量 excelDataMapper import com id


源码:https://gitee.com/antia11/excel-data-import-demo
背景:客户需要每周会将上传一个 Excel 数据文件,数据量单次为 20W 以上,作为其他模块和报表的基础数据。

客户需求分析:

  1. 数据量为 20W 条左右。
  2. 数据需要去重。
  3. 等待时间不能太长。
  4. 文件中会有错误数据存在,错误数据跳过不进入数据库。

注意点:

  1. 为提高导入速度,选择分批插入,每次插入 1000 条数据。
  2. 在读取数据时判断数据是否正确,不正确不插入。
  3. 对数据进行去重。

实现逻辑:

  1. 首先使用 EasyExcel 实现分批插入数据。
  2. 数据插入完成后,在数据库使用 SQL 的方式进行去重,避免内存溢出。
package com.antia1.demo.service;

import com.alibaba.excel.EasyExcel;
import com.antia1.demo.entity.ExcelDataEntity;
import com.antia1.demo.listener.ExcelDataListener;
import com.antia1.demo.mapper.ExcelDataMapper;
import com.antia1.demo.util.RespBean;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.Map;

/**
 * Author: anti
 * Date: 2022/7/23 16:13
 */
@Service
@Slf4j
public class ExcelDataService {

    @Autowired
    private ExcelDataMapper excelDataMapper;


    public RespBean importData(MultipartFile file) throws IOException {
        //0.获取数据库中的最大id
        Map<String, Object> idMap = excelDataMapper.getMaxId();
        int maxId = Integer.parseInt(idMap.get("maxId") + "");

        //1.读取excel
        EasyExcel.read(file.getInputStream(), ExcelDataEntity.class,new ExcelDataListener(excelDataMapper,maxId)).sheet().doRead();

        //2.开始去除重复数据
        log.debug("全部导入完成,开始进行数据去重");
        int count = excelDataMapper.deleteDuplicates();
        log.debug("去除重复数据:{}条",count);

        return RespBean.ok("导入完成");
    }
}

package com.antia1.demo.listener;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.antia1.demo.entity.ExcelDataEntity;
import com.antia1.demo.mapper.ExcelDataMapper;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;

/**
 * Author: anti
 * Date: 2022/7/23 16:10
 */
@Slf4j
public class ExcelDataListener extends AnalysisEventListener<ExcelDataEntity> {

    private static final int BATCH_COUNT = 1000;

    private List<ExcelDataEntity> list = new ArrayList<>();

    private ExcelDataMapper excelDataMapper;

    private int primaryKey;

    private int totalCount;

    public ExcelDataListener(ExcelDataMapper excelDataMapper, int primaryKey) {
        this.excelDataMapper = excelDataMapper;
        this.primaryKey = primaryKey;
    }

    @Override
    public void invoke(ExcelDataEntity excelDataEntity, AnalysisContext analysisContext) {
        primaryKey ++ ;
        excelDataEntity.setId(String.valueOf(primaryKey));
        list.add(excelDataEntity);
        if(list.size() >= BATCH_COUNT){
            saveData();
            list.clear();
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        saveData();
        System.out.println(String.format("数据同步完成,总数量为:%s",totalCount));
    }


    public void saveData(){
        if(list.size()>0){
            int count = excelDataMapper.insertBatch(list);
            totalCount += count;
        }
    }
}

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.antia1.demo.mapper.ExcelDataMapper">
  
  <!--数据插入-->
  <insert id="insertBatch" parameterType="java.util.List">
    INSERT INTO `demo`.`tb_exceldata` (
    `id`,
    `code`,
    `desc`,
    `objectCode`,
    `projectCode`,
    `other`
    )
    VALUES
    <foreach collection="list" item="item" separator=",">
      (#{item.id}, #{item.code}, #{item.desc}, #{item.objectCode},#{item.projectCode},#{item.other})
    </foreach>
  </insert>
  
  <!--查询最大id-->
  <select id="getMaxId" resultType="java.util.Map">
    SELECT IFNULL(MAX(CAST(id AS SIGNED)),0) AS maxId FROM `demo`.`tb_exceldata`
  </select>
  
  <!--去除重复数据-->
  <delete id="deleteDuplicates">
    DELETE
    FROM
    `tb_exceldata`
    WHERE
    id NOT IN (
    SELECT
    t.id
    FROM
    ( SELECT MIN( id ) AS id FROM `tb_exceldata` GROUP BY `code`,`desc`,`objectCode`,`projectCode`,`other`) t
    )
  </delete>
  
</mapper>

标签:antia1,demo,EasyExcel,导入,数据量,excelDataMapper,import,com,id
来源: https://www.cnblogs.com/antaia11/p/16515420.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有