Easyexcel分批读取excel数据,海量excel数据量的读取存入数据库的实际操作

该博客介绍了如何利用阿里巴巴的EasyExcel工具进行大数据量Excel的分批读取和入库操作,以避免内存溢出。通过监听器方式,设置每批次1000条数据进行数据库存储,确保高效且稳定的处理大量数据。同时,提供了读取和存储的代码示例,以及实体对象的注解方式,帮助开发者理解并应用到实际项目中。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        对于海量excel的数据读取,如获取对账文件,第三方订单信息等等,为了避免内存溢出,我们通常会进行分批读取入库的操作,这里我们使用阿里巴巴开源的 easyexcel 工具类进行操作,为了减少踩坑,我们先看官网,官网写的很清晰, 个人也是按照官网的代码示例来进行操作,这里只使用监听方式读取

这里使用监听器的方式,根据设置每批次数据量的大小,当list里面数据量达到设置每批次最大数据量时,进行入库操作,海量数据的话,通常每批次1000的速度最快,贴一下代码,下面做一下解释,首先引入maven组件

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>2.1.6</version>
        </dependency>

监听方式 读取代码,参数看个人需要进行配置

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.fastjson.JSON;
import com.qx.boot.trm.controller.AgtPftDayStlController;
import com.qx.boot.trm.dto.CheckTransInfoDto;
import com.qx.boot.trm.mapper.CheckTransInfoMapper;
import com.qx.boot.util.utils.TdDateUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

/**
 * @version V1.0
 * @author: hqk
 * @date: 2020/12/30 10:52
 * @Description: 对账excel读取, 用于大数据量 excel 导入监听器, 用于循环处理excel 保存数据
 *       此类不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
 */
public class ExcelModelListener extends AnalysisEventListener<CheckTransInfoDto> {

    private Logger logger = LoggerFactory.getLogger(ExcelModelListener.class);

    /**
     * 每隔 1000条,然后清理list ,方便内存回收
     */
    private static final int BATCH_COUNT = 1000;

    // 存款的list对象
    List<CheckTransInfoDto> list = new ArrayList<CheckTransInfoDto>();

    // 存储数据的 dao层
    private CheckTransInfoMapper checkTransInfoMapper;

    // 自定义参数 不需要可以去掉 需要多少可以自己加
    private String checkDt;

    /**
     * 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
     * 
     * @param checkTransInfoMapper
     */
    public ExcelModelListener(CheckTransInfoMapper checkTransInfoMapper,String checkDt) {
        this.checkTransInfoMapper = checkTransInfoMapper;
        this.checkDt = checkDt;
    }

    public ExcelModelListener() {
    }

    /**
     * 这个每一条数据解析都会来调用
     *
     * @param checkTransInfoDto
     *            one row value. Is is same as {@link AnalysisContext#readRowHolder()}
     * @param analysisContext
     */
    @Override
    public void invoke(CheckTransInfoDto checkTransInfoDto, AnalysisContext analysisContext) {

        list.add(checkTransInfoDto);
        // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
        if (list.size() >= BATCH_COUNT) {
            saveData();
            // 存储完成清理 list
            list.clear();
        }
    }

    /**
     * 所有数据解析完成了 都会来调用
     *
     * @param analysisContext
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        // 这里也要保存数据,确保最后遗留的数据也存储到数据库
        saveData();
        logger.info("所有数据解析完成!");
    }

    /**
     * 存储数据
     */
    private void saveData() {
        logger.info("{}条数据,开始存储数据库!", list.size());
        //checkTransInfoMapper.saveCheckTransInfo(list, checkDt);
        for (int i = 0; i < list.size() ; i++) {
            System.out.println(JSON.toJSONString(list.get(i)));
        }
        logger.info("存储数据库成功!");
    }
}

实体对象里面,这里用注解方式,和excel表头字段一一对应

/**
 * @version V1.0
 * @author: hqk
 * @date: 2020/12/30 19:49
 * @Description: 读取对账 excel 实体
 */
public class CheckTransInfoDto {

    /** 交易订单号 */
    @ExcelProperty(value = "交易订单号")
    private String transOrderNo;

    /** 交易商户编号 */
    @ExcelProperty(value = "交易商户编号")
    private String transMercId;

    /** 结算商户编号 */
    @ExcelProperty(value = "结算商户编号")
    private String smtMercId;

    /** 交易银行卡号 */
    @ExcelProperty(value = "银行卡号")
    private String crdNo;

    // get set 方法
}

 接下来看一下如何调用

@RestController
public class TestController {


    @Autowired
    private CheckTransInfoMapper checkTransInfoMapper;

    @RequestMapping("testExcel")
    public void test(){

        EasyExcel.read(filePath, CheckTransInfoDto.class,
                new ExcelModelListener(checkTransInfoMapper,"20210115")).sheet().doRead();
    }
}

’官网写的也很详细,按照官网来就可以的,这样就可以实现分批读取Excel的数据了,

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值