easyexcel大数据多线程读取后导出

这篇具有很好参考价值的文章主要介绍了easyexcel大数据多线程读取后导出。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

最近在研究大数据的导入导出,由此想到了在管理系统中,excel导入导出都是常见操作,故我的操作由此开始。
首先是选择适合的工具类,alibaba开源的easyexcel比较好,处理大数据效率较高,故选用此工具,这是easyexcel官网
1.导入maven依赖

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

2.配置好相应的实体类

package com.example.admin.domain;


import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.example.admin.execl.TimestampStringConverter;
import lombok.Data;

import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Timestamp;

@Data
@TableName("example")//@TableName中的值对应着表名
public class Example implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 主键
     */
    @ExcelIgnore
    @TableId(type = IdType.AUTO)
    private Long id;

    /**
     * 姓名
     */
    @ExcelProperty(value = "姓名", index = 0)
    @ColumnWidth(16)
    private String name;

    /**
     * 状态
     */
    @ExcelIgnore
    @TableLogic
    private String status;

    /**
     * 创建时间
     */
    @ExcelProperty(value = "创建时间", index = 1, converter = TimestampStringConverter.class)
    @ColumnWidth(28)
    private Timestamp createTime;

    /**
     * 更新时间
     */
    @ExcelProperty(value = "更新时间", index = 2, converter = TimestampStringConverter.class)
    @ColumnWidth(28)
    private Timestamp updateTime;

    /**
     * 金额
     */
    @ExcelProperty(value = "金额", index = 3)
    @ColumnWidth(16)
    private BigDecimal money;

    /**
     * 数量
     */
    @ExcelProperty(value = "数量", index = 4)
    @ColumnWidth(16)
    private BigInteger num;

}

Timestamp需要类型转化,具体参考大神博客和大神博客

package com.example.admin.execl;

import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.alibaba.excel.util.DateUtils;

import java.sql.Timestamp;

/**
 * @author yss
 * @date 2023/3/3
 */
public class TimestampStringConverter implements Converter<Timestamp> {

    @Override
    public Class<?> supportJavaTypeKey() {
        return Timestamp.class;
    }

    @Override
    public CellDataTypeEnum supportExcelTypeKey() {
        return CellDataTypeEnum.STRING;
    }

    @Override
    public WriteCellData<?> convertToExcelData(Timestamp value, ExcelContentProperty contentProperty,
                                               GlobalConfiguration globalConfiguration) {
        WriteCellData cellData = new WriteCellData();
        String cellValue;
        if (contentProperty == null || contentProperty.getDateTimeFormatProperty() == null) {
            cellValue = DateUtils.format(value.toLocalDateTime(), null, globalConfiguration.getLocale());
        } else {
            cellValue = DateUtils.format(value.toLocalDateTime(), contentProperty.getDateTimeFormatProperty().getFormat(),
                    globalConfiguration.getLocale());
        }
        cellData.setType(CellDataTypeEnum.STRING);
        cellData.setStringValue(cellValue);
        cellData.setData(cellValue);
        return cellData;
    }
}

3.多线程读取数据库数据,存放到一个map集合中,然后遍历集合写入到excel;注意 easyexcel不支持多线程写入。


    @Autowired
    @Qualifier("excelThreadPool")
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    @Test
    public void contextTest(){
        // 每页多少条数据
        int pageSize = 50000;
        // 导出文件路径
        String fileName = "d:\\test.xlsx";
        // 查询条件
        QueryWrapper<Example> queryWrapper = new QueryWrapper<>();
        Long start = System.currentTimeMillis();
        Long count = exampleMapper.selectCount(queryWrapper);
        Long sheetNum = count % pageSize == 0 ? count / pageSize:count / pageSize + 1;
        // 多线程去读
        // 1.初始化map容量 防止扩容带来的效率损耗
        Map<Integer, Page<Example>> pageMap = new ConcurrentHashMap<>(Math.toIntExact(sheetNum));
        CountDownLatch countDownLatch = new CountDownLatch(Math.toIntExact(sheetNum));
        // 注意 easyexcel 暂时不支持多线程并发写入!!! 详情请看github上issues
        for (int i = 0 ;i< sheetNum;i++){
            int finali = i;
            threadPoolTaskExecutor.submit(()->{
                Page<Example> page = new Page<>();
                page.setCurrent(finali + 1);
                page.setSize(pageSize);
                // 获取数据存放到map中
                Page<Example> selectPage = exampleMapper.selectPage(page,queryWrapper);
                pageMap.put(finali,selectPage);
                // 消耗掉一个
                countDownLatch.countDown();
            });
        }
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 写入
        try (ExcelWriter excelWriter = EasyExcel.write(fileName, Example.class).build()) {
            pageMap.forEach((k,v)->{
                log.info("正在写入{}条数据",pageSize);
                WriteSheet writeSheet = EasyExcel.writerSheet(k, "第"+(k+1)+"批数据").build();
                excelWriter.write(v.getRecords(), writeSheet);
                // 写完当前数据立刻删除  不删除会产生内存泄漏即无法回收Map中巨大的空间 导致oom
                pageMap.remove(k);
            });
            excelWriter.finish();
        }
        Long end = System.currentTimeMillis();
        log.info("耗时"+(end-start)+"ms");

    }

线程池操作类

package com.example.admin.utils;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author yss
 * @date 2023/3/3
 */
@Configuration
public class ConcurrentThreadGlobalConfig {
    @Bean("excelThreadPool")
    public ThreadPoolTaskExecutor defaultThreadPool() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //核心线程数目
        executor.setCorePoolSize(Runtime.getRuntime().availableProcessors()+1);
        //指定最大线程数
        executor.setMaxPoolSize(Runtime.getRuntime().availableProcessors()+1);
        //队列中最大的数目
        executor.setQueueCapacity(650);
        //线程名称前缀
        executor.setThreadNamePrefix("DefaultThreadPool_");
        //rejection-policy:当pool已经达到max size的时候,如何处理新任务
        //CALLER_RUNS:不在新线程中执行任务,而是由调用者所在的线程来执行
        //对拒绝task的处理策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //线程空闲后的最大存活时间
        executor.setKeepAliveSeconds(60);
        //加载
        executor.initialize();

        return executor;
    }
}

导出1000w条数据,用时5分钟左右,这个效率还是可以的
easyexcel大数据多线程读取后导出
easyexcel大数据多线程读取后导出
这是导出的操作,明天继续研究大数据导入操作!!!文章来源地址https://www.toymoban.com/news/detail-513447.html

到了这里,关于easyexcel大数据多线程读取后导出的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spring boot easyexcel 实现复合数据导出、按模块导出

    场景: 导出数据为1对多的复合数据 一个模块是一条数据,直接填充数据无法实现 如图: 红框内为一条数据(1对多),下方箭头指向为第二条数据 如果直接填充,只能填充第一条,第二条就没办法了。 由于多行都包含许多,固定表头,只能走填充路线,怎么实现呢 实现思路

    2024年02月07日
    浏览(41)
  • 基于EasyExcel的数据导入导出(复制可用)

    目录   前言: 新建SpringBoot项目,引入下面的依赖 数据导入导出执行原理和思路: 用户端逻辑: 后台开发逻辑: 代码实现 下拉框策略 批注策略 数据读取监听 Excel工具类 创建导入数据模板类 创建数据导出模板 Web接口 结果展示 模板下载 数据导入 数据导出   代码复制粘贴

    2024年02月05日
    浏览(45)
  • 使用Apache POI数据导出及EasyExcel进行十万、百万的数据导出

    Apache POI 是基于 Office Open XML 标准( OOXML )和 Microsoft 的 OLE 2 复合⽂档 格式( OLE2 )处理各种⽂件格式的开源项⽬。 简⽽⾔之,您可以使⽤ Java 读写 MS Excel ⽂件,可以使⽤ Java 读写 MS Word 和 MS PowerPoint ⽂件。 1.HSSF - 提供读写 Microsoft Excel XLS 格式 (Microsoft Excel 97 (-2003)) 档案

    2024年02月15日
    浏览(41)
  • SpringBoot使用EasyExcel批量导出500万数据

    记录下学习SpringBoot使用EasyExcel批量导出百万数据。留着以后备用。 本地环境mysql安装的5.7版本,项目使用jdk1.8版本,项目使用的mysql驱动版本为8.0版本。 这一篇博客内容代码基于我的这篇博客: SpringBoot使用mybatis批量新增500万数据到mysql数据库Demo,在自己这篇博客的代码上做

    2024年02月12日
    浏览(40)
  • 使用easyexcel填充模板数据,并导出excel

    导出excel功能非常场景,本片文章记录如何使用模板填充数据后再导出。因直接导出excel数据样式不符合要求,所以做了模板填充然后再导出excel。 效果如下: 注意:列表数据变量名前面要写点{.id},如果单条数据可以不写。 使用表单提交: 实体代码: controller代码: 只对je

    2024年03月11日
    浏览(50)
  • EasyExcel导出带下拉选数据的Excel数据导入模板

    #因为项目中需要导入一些信息,但是这些信息比较不常见,且在项目字典数据中维护有这些数据,所以在导出模板的时候,把这些数据一并导出,可以减少用户的编写,避免在导入的时候因为数据错误,发生一些业务问题 直接开始 1、以岗位类型为例,展示数据的实现方式

    2024年02月03日
    浏览(46)
  • EasyExcel如何导出数据?超级简单,看这就够了

    我们可以在官网找到相关代码 前端我们直接调用这个方法就行 其实很简单,只需要在我们实体类上加上 用法如下所示 easyExcel是一个非常简单好用的数据导出导入工具,easyexcel重写了poi对07版Excel的解析,一个3M的excel用POI sax解析依然需要100M左右内存,改用easyexcel可以降低到

    2024年02月11日
    浏览(46)
  • 使用EasyExcel实现excel导出,支持百万大数据量导出-----超简单

    通过设置sheet数量,完成分批导出,每个sheet存100万数据,每次查询插入20万数据,避免超时,内存溢出等问题,可以根据服务器配置调整参数设置。 1.引入依赖 2.创建对应的实体类 @ExcelProperty设置的就是导出的列名,还可以设置排序等等 3.核心导出代码 4.配置类 至此就完成导

    2024年02月11日
    浏览(60)
  • 【EasyExcel】在SpringBoot+VUE项目中引入EasyExcel实现对数据的导出(封装工具类)

    一、引入EasyExcel 通过maven引入,坐标如下: 二、后端代码演示 下面以权限系统中的角色列表为案例,演示如何导出数据 实体类 工具类 通过@Component把工具类交给spring管理,在需要使用的地方使用@Resource注入即可 将泛型设置为 \\\" ? \\\",来表示任意类型,可以通过这一个方法完成

    2024年02月16日
    浏览(56)
  • 万级数据优化EasyExcel+mybatis流式查询导出封装

    时间 更新内容 2023/09/23 fix: 每个sheet大小和存储内存条数一致的bug update: 增大一个sheet的默认容量 我们不妨先给大家讲一个概念,利用此概念我们正好给大家介绍一个数据库优化的小技巧: 需求如下:将一个地市表的数据导出70万条。 如果你不假思索,直接一条sql语句搞上去

    2024年02月11日
    浏览(56)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包