源码: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>

基于EasyExcel的大数据量导入并去重的更多相关文章

  1. Mysql 大数据量导入程序

    Mysql 大数据量导入程序<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" ...

  2. java excel大数据量导入导出与优化

    package com.hundsun.ta.utils; import java.io.File; import java.io.FileOutputStream; import java.io.I ...

  3. JAVA JDBC大数据量导入Mysql

    转自https://blog.csdn.net/q6834850/article/details/73726707?tdsourcetag=s_pctim_aiomsg 采用JDBC批处理(开启事务. ...

  4. 【Java POI】POI基于事件驱动解析大数据量2007版本Excel,空值导致列错位问题

    1.目前测试了20M的文件,可以读取. 2.支持单个工作表1万+的数据行数,耗时如图. 3.以下是关键地方处理的代码 //Accepts objects needed while parsing. / ...

  5. SQL Server 使用bcp进行大数据量导出导入

    转载:http://www.cnblogs.com/gaizai/archive/2010/04/17/1714389.html SQL Server的导出导入方式有: 在SQL Server中提供了 ...

  6. 使用OPENROWSET、Microsoft.ACE.OLEDB实现大数据量的高效导入

    首先说明使用的环境是:java和Sqlserver. 最近公司需要进行大数据量的导入操作.原来使用的是Apache POI,虽然可以实现功能,但是因为逻辑处理中需要进行许多校验,处理速度太慢,使用多线 ...

  7. MYSQL数据库导入大数据量sql文件失败的解决方案

    1.在讨论这个问题之前首先介绍一下什么是"大数据量sql文件". 导出sql文件.选择数据库-----右击选择"转储SQL文件"-----选择"结构和 ...

  8. MySQL数据库如何解决大数据量存储问题

    利用MySQL数据库如何解决大数据量存储问题? 各位高手您们好,我最近接手公司里一个比较棘手的问题,关于如何利用MySQL存储大数据量的问题,主要是数据库中的两张历史数据表,一张模拟量历史数据和一张开 ...

  9. 利用MySQL数据库如何解决大数据量存储问题?

    提问:如何设计或优化千万级别的大表?此外无其他信息,个人觉得这个话题有点范,就只好简单说下该如何做,对于一个存储设计,必须考虑业务特点,收集的信息如下:1.数据的容量:1-3年内会大概多少条数据,每条 ...

随机推荐

  1. Docker被禁了!只能靠它了......

    科技飞速发展的今天,企业对候选人有了新的更高要求,如市场.运营等必须会Python.Sql,面试常问诸如用户漏斗等考察数据分析能力.可以说,懂数据的人会更有竞争力通过面试. 而市场上,专业的数据分析人 ...

  2. 4┃音视频直播系统之浏览器中通过 WebRTC 进行桌面共享

    一.共享桌面原理 共享桌面在直播系统中是一个必备功能 共享者:每秒钟抓取多次屏幕,每次抓取的屏幕都与上一次抓取的屏幕做比较,取它们的差值,然后对差值进行压缩:如果是第一次抓屏或切幕的情况,即本次抓取的 ...

  3. 手把手教你 bash中给变量赋值时 ' 和 " 和 ` 和 $() 的使用

    1.赋值指令 var='变量内容' var="变量内容" var=`command` var=$(command) var=变量内容 2.格式要求 =两边不能有空白字符 错误示例 ...

  4. 【多线程】线程同步 synchronized

    由于同一进程的多个线程共享同一块存储空间 , 在带来方便的同时,也带来了访问 冲突问题 , 为了保证数据在方法中被访问时的正确性 , 在访问时加入 锁机制synchronized , 当一个线程获得对 ...

  5. elemetnUI表格分别给列表每一个按钮加loading

    // 获取列表数据的时候--添加按钮loading this.list = this.list.map((item) => { this.$set(item, "dataLoading ...

  6. ptorch常用代码梯度篇(梯度裁剪、梯度累积、冻结预训练层等)

    梯度裁剪(Gradient Clipping) 在训练比较深或者循环神经网络模型的过程中,我们有可能发生梯度爆炸的情况,这样会导致我们模型训练无法收敛. 我们可以采取一个简单的策略来避免梯度的爆炸,那 ...

  7. 测试平台系列(95) 前置条件支持简单的python脚本

    大家好~我是米洛! 我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的教程,希望大家多多支持. 欢迎关注我的公众号米洛的测开日记,获取最新文章教程! 回顾 上一节我们构思了一下怎么去支 ...

  8. 深度学习与CV教程(10) | 轻量化CNN架构 (SqueezeNet,ShuffleNet,MobileNet等)

    作者:韩信子@ShowMeAI 教程地址:http://www.showmeai.tech/tutorials/37 本文地址:http://www.showmeai.tech/article-det ...

  9. 技术分享 | app自动化测试(Android)--高级定位技巧

    原文链接 XPath高级定位技巧 XPath 简介 XPath 的英文全称为:XML Path Language,意旨对 XML 中的元素进行路径定位的一种语言,它可适用 XML 标记语言,Html ...

  10. .NET打包应用设置成自包含

    设置项目的配置文件 在项目的配置文件(.csproj文件)中加入RuntimeIdentifier节点,节点的内容为要打包进入最终程序的目标运行时.更多平台标识符,请看这里RIDs. <Prop ...