对于海量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的数据了,

GitHub 加速计划 / ea / easyexcel
31.64 K
7.47 K
下载
快速、简洁、解决大文件内存溢出的java处理Excel工具
最近提交(Master分支:3 个月前 )
c42183df Bugfix 3 个月前
efa7dff6 * 重新加回 `commons-io` 3 个月前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐