百万数据快速导入导出

百万数据快速导入

pom

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

在这里插入图片描述
在这里插入图片描述

	@Resource
    private SalariesListener salariesListener;

    private ExecutorService executorService = Executors.newFixedThreadPool(20);

    /**
     * 同步导入
     * @param file
     * @throws IOException
     */
    public void importExcel(MultipartFile file) throws IOException {
        EasyExcel.read(file.getInputStream(), Salaries.class, salariesListener).doReadAll();
    }


    /**
     * 异步导入
     * @param file
     */
    public void importExcelAsync(MultipartFile file) {
        // 开20个线程分别处理20个sheet
        try {
            InputStream inputStream = file.getInputStream();
            int activeSheetIndex = new XSSFWorkbook(inputStream).getNumberOfSheets();//多少个sheet  20

            List<Callable<Object>> tasks = new ArrayList<>(activeSheetIndex);
            for (int i = 0; i < activeSheetIndex; i++) {
                int num = i;
                tasks.add(() -> {
                    EasyExcel.read(inputStream, Salaries.class, salariesListener)
                            .sheet(num).doRead();
                    return null;
                });
            }

            executorService.invokeAll(tasks);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

监听器代码

@Component
public class SalariesListener extends ServiceImpl<SalariesMapper, Salaries> implements ReadListener<Salaries>, IService<Salaries> {

    private static final Log logger = LogFactory.getLog(SalariesListener.class);

    private ExecutorService executorService = Executors.newFixedThreadPool(20);

    private ThreadLocal<ArrayList<Salaries>> salariesList = ThreadLocal.withInitial(ArrayList::new);
    private static AtomicInteger count = new AtomicInteger(1);
    private static final int batchSize = 10000;

    @Resource
    private SalariesListener salariesListener;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void invoke(Salaries data, AnalysisContext context) {
//        saveOne(data);

        ArrayList<Salaries> salaries = salariesList.get();
        salaries.add(data);
        if (salaries.size() >= batchSize) {
//            saveData();
            asyncSaveData();
        }
    }

    public void saveOne(Salaries data){
        save(data);
        logger.info("第" + count.getAndAdd(1) + "次插入1条数据");
    }

    public void saveData() {
        if (!salariesList.get().isEmpty()) {
            saveBatch(salariesList.get(), salariesList.get().size());
            logger.info("第" + count.getAndAdd(1) + "次插入" + salariesList.get().size() + "条数据");
            salariesList.get().clear();
        }
    }

    public void asyncSaveData() {
        if (!salariesList.get().isEmpty()) {
            ArrayList<Salaries> salaries = (ArrayList<Salaries>) salariesList.get().clone();
            executorService.execute(new SaveTask(salaries, salariesListener));
            salariesList.get().clear();
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void doAfterAllAnalysed(AnalysisContext context) {
        logger.info("一个Sheet全部处理完");
        if (salariesList.get().size() >= batchSize) {
            saveData();
        }
    }

    static class SaveTask implements Runnable {

        private List<Salaries> salariesList;
        private SalariesListener salariesListener;

        public SaveTask(List<Salaries> salariesList, SalariesListener salariesListener) {
            this.salariesList = salariesList;
            this.salariesListener = salariesListener;
        }

        @Override
        public void run() {
            salariesListener.saveBatch(salariesList);
            logger.info("第" + count.getAndAdd(1) + "次插入" + salariesList.size() + "条数据");
        }
    }
}

百万数据快速导出

public static final String CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";

    @Resource
    private SalariesMapper salariesMapper;

    public void exportExcel1(HttpServletResponse response) throws IOException {
        setExportHeader(response);
        List<Salaries> salaries = salariesMapper.selectList(null);
        EasyExcel.write(response.getOutputStream(), Salaries.class).sheet().doWrite(salaries);
    }

    public void exportExcel2(HttpServletResponse response) throws IOException {
        setExportHeader(response);
        List<Salaries> salaries = salariesMapper.selectList(null);
        try (ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream(), Salaries.class).build()) {
            WriteSheet writeSheet1 = EasyExcel.writerSheet(1, "模板1").build();
            WriteSheet writeSheet2 = EasyExcel.writerSheet(2, "模板2").build();
            WriteSheet writeSheet3 = EasyExcel.writerSheet(3, "模板3").build();

            List<Salaries> data1 = salaries.subList(0, salaries.size() / 3);
            List<Salaries> data2 = salaries.subList(salaries.size() / 3, salaries.size() * 2 / 3);
            List<Salaries> data3 = salaries.subList(salaries.size() * 2 / 3, salaries.size());


            excelWriter.write(data1, writeSheet1);
            excelWriter.write(data2, writeSheet2);
            excelWriter.write(data3, writeSheet3);
        }
    }



    public void exportExcel3(HttpServletResponse response) throws IOException {

        setExportHeader(response);

        try (ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream(), Salaries.class).build()) {

            Long count = salariesMapper.selectCount(null);
            Integer pages = 10;
            Long size = count / pages;

            for (int i = 0; i < pages; i++) {
                WriteSheet writeSheet = EasyExcel.writerSheet(i, "模板" + i).build();

                Page<Salaries> page = new Page<>();
                page.setCurrent(i + 1);
                page.setSize(size);
                Page<Salaries> selectPage = salariesMapper.selectPage(page, null);

                excelWriter.write(selectPage.getRecords(), writeSheet);
            }
        }
    }


    public void exportExcel4(HttpServletResponse response) throws IOException, InterruptedException {

        setExportHeader(response);

        Long count = salariesMapper.selectCount(null);

        Integer pages = 20;
        Long size = count / pages;

        ExecutorService executorService = Executors.newFixedThreadPool(pages);
        CountDownLatch countDownLatch = new CountDownLatch(pages);

        Map<Integer, Page<Salaries>> pageMap = new HashMap<>();
        for (int i = 0; i < pages; i++) {
            int finalI = i;
            executorService.submit(()-> {
                Page<Salaries> page = new Page<>();
                page.setCurrent(finalI + 1);
                page.setSize(size);
                Page<Salaries> selectPage = salariesMapper.selectPage(page, null);

                pageMap.put(finalI, selectPage);
                countDownLatch.countDown();

            });
        }

        countDownLatch.await();

        try (ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream(), Salaries.class).build()) {
            for (Map.Entry<Integer, Page<Salaries>> entry : pageMap.entrySet()) {
                Integer num = entry.getKey();
                Page<Salaries> salariesPage = entry.getValue();
                WriteSheet writeSheet = EasyExcel.writerSheet(num, "模板" + num).build();
                excelWriter.write(salariesPage.getRecords(), writeSheet);
            }
        }

        // https://github.com/alibaba/easyexcel/issues/1040
    }

    private static void setExportHeader(HttpServletResponse response) {
        response.setContentType(CONTENT_TYPE);
        response.setCharacterEncoding(StandardCharsets.UTF_8.name());
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + "zhouyu.xlsx");
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/51623.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

求解方程x^2=a的根,不使用库函数直接求解(不动点迭代法)

首先可以将方程两边同时加上x&#xff0c;&#xff0c;这时候两边同时再除以1x&#xff0c;就得到了&#xff0c;变形为。&#xff08;变性后的迭代式不唯一&#xff0c;这里随便选取一个&#xff09; 当x是准确值的时候&#xff0c;两边应该是相等的&#xff0c;如果x是近似值…

【Git】分支管理之创建、切换、合并、删除分支以及冲突处理

目录 一、理解分支 二、创建、切换、合并分支 三、删除分支 四、冲突处理 五、合并模式 六、合并策略 七、Bug分支处理 八、强制删除分支 一、理解分支 master其实就是一个指针 &#xff0c;他指向的是主分支最近一次commit。我们可以创建新的分支&#xff0c;在新的分…

Arcgis之 KML/KMZ文件转shp

一般我们在Goole Earth上勾画的区域导出后都为KML或者KMZ格式的&#xff0c;但无法在arcgis等软件上直接应用&#xff0c;故需进行一定的转换 1.打开ArcMap&#xff0c;选择ArcToolbox->Conversion Tools->From KML->KML To Layer 得到如下结果&#xff08;由于本KML…

请问学JavaScript 前要学html 和css 吗?

前言 html和css可以理解为是一个网站的骨架和皮肤&#xff0c;这两部分做好后整个网站的外观展示的完成度基本就有了个90%左右&#xff0c;所以在学习js前是需要学习html和css 的&#xff0c;这两部分不用花特别多的时间&#xff08;虽然css如果想做一些非常炫酷的效果个人认为…

什么是SVM算法?硬间隔和软间隔的分类问题

SVM全称是supported vector machine(支持向量机)&#xff0c;即寻找到一个超平面使样本分成两类&#xff0c;并且间隔最大。 SVM能够执行线性或⾮线性分类、回归&#xff0c;甚至是异常值检测任务。它是机器学习领域最受欢迎的模型之一。SVM特别适用于中小型复杂数据集的分类。…

MobaXterm通过SSH访问Ubuntu服务器遇到的一个问题

在Windows下的MobaXterm界面配置完ubuntuIP以后显示access denied&#xff0c;排查发现是因为在ubuntu那边忘记安装了SSH Serve&#xff0c;安装过程如下&#xff1a; 第一步&#xff1a;安装所需包 让我们从打开终端输入一些必要命令开始。 注意&#xff0c;在安装新的包或…

SpringBoot统一异常处理和统一返回格式

上篇博客我们讲解了使用AOP来进行统一的用户登录判断&#xff0c;其实像这种功能统一且使用较多的地方&#xff0c;都可以用AOP来处理&#xff0c;除了统⼀的⽤户登录判断之外&#xff0c;AOP 还可以实现&#xff1a; 统⼀⽇志记录统⼀⽅法执⾏时间统计&#xff08;在性能优化…

机器学习:混合高斯聚类GMM(求聚类标签)+PCA降维(3维降2维)习题

使用混合高斯模型 GMM&#xff0c;计算如下数据点的聚类过程&#xff1a; Datanp.array([1,2,6,7]) 均值初值为: μ1,μ21,5 权重初值为: w1,w20.5,0.5 方差: std1,std21,1 K2 10 次迭代后数据的聚类标签是多少&#xff1f; 采用python代码实现&#xff1a; from scipy import…

人工智能-Dlib+Python实现人脸识别(人脸识别篇)

人脸识别流程 人脸检测,人脸数据提取:首先是检测到人脸保存人脸数据:可以保存到mysql数据库中mysql数据库连接mysql数据库安装mysql数据库操作设置人脸数据标签:(人脸名字),保存到数据库打开摄像头,检测到人脸,提取人脸数据:人脸数据与数据库中的数据对比,1、人脸检…

【图论】Prim算法

一.介绍 Prim算法是一种用于解决最小生成树问题的贪心算法。最小生成树问题是指在一个连通无向图中找到一个生成树&#xff0c;使得树中所有边的权重之和最小。 Prim算法的基本思想是从一个起始顶点开始&#xff0c;逐步扩展生成树&#xff0c;直到覆盖所有顶点。具体步骤如下…

用合成数据训练托盘检测模型【机器学习】

想象一下&#xff0c;你是一名机器人或机器学习 (ML) 工程师&#xff0c;负责开发一个模型来检测托盘&#xff0c;以便叉车可以操纵它们。 ‌你熟悉传统的深度学习流程&#xff0c;已经整理了手动标注的数据集&#xff0c;并且已经训练了成功的模型。 推荐&#xff1a;用 NSDT设…

【业务功能篇60】Springboot + Spring Security 权限管理 【终篇】

4.4.7 权限校验扩展 4.4.7.1 PreAuthorize注解中的其他方法 hasAuthority&#xff1a;检查调用者是否具有指定的权限&#xff1b; RequestMapping("/hello")PreAuthorize("hasAuthority(system:user:list)")public String hello(){return "hello Sp…

深度学习入门教程(1):用神经网络预测糖尿病病例Predict Diabetes Cases with Neural Networks

本深度学习入门教程是在polyu HPCStudio 启发以及资源支持下进行的&#xff0c;在此也感谢polyu以及提供支持的老师。 大纲&#xff08;what will you learn from this project&#xff09; 1&#xff1a;What are neural networks&#xff1f; 2&#xff1a;Why use neural …

3D 渲染技巧-如何创建高质量写实渲染?

掌握创建高质量建筑渲染和任何 3D 渲染的艺术是一项复杂且需要技巧的工作&#xff0c;通常需要多年的经验和实践。实现逼真的结果需要仔细考虑众多因素&#xff0c;并避免可能导致缺乏真实性的假渲染效果的常见错误。 避免常见错误 - 提升渲染游戏的技巧 在追求创建真正逼真的…

从零开始学习CTF——CTF是什么

引言&#xff1a; 从2019年10月开始接触CTF&#xff0c;学习了sql注入、文件包含等web知识点&#xff0c;但都是只知道知识点却实用不上&#xff0c;后来在刷CTF题才发现知识点的使用方法&#xff0c;知道在哪里使用&#xff0c;哪里容易出漏洞&#xff0c;可是在挖src漏洞中还…

Appium+python自动化(二十四) - 元素等待(超详解)

思考 在自动化过程中&#xff0c;元素出现受网络环境&#xff0c;设备性能等多种因素影响。因此元素加载的时间可能不一致&#xff0c;从而会导致元素无法定位超时报错&#xff0c;但是实际上元素是正常加载了的&#xff0c;只是出现时间晚一点而已。那么如何解决这个问题呢&am…

【业务功能篇57】Springboot + Spring Security 权限管理 【上篇】

4.权限管理模块开发 4.1 权限管理概述 4.1.1 权限管理的意义 后台管理系统中&#xff0c;通常需要控制不同的登录用户可以操作的内容。权限管理用于管理系统资源&#xff0c;分配用户菜单、资源权限&#xff0c;以及验证用户是否有访问资源权限。 4.1.2 RBAC权限设计模型 …

Scratch 教程 之 如何四舍五入保留一个小数到指定的数位

有些时候&#xff0c;我们需要四舍五入一个多位小数到指定的位&#xff0c;但scratch并没有这个积木&#xff0c;怎么做呢&#xff1f;我来教你&#xff5e; 我们创建一个函数&#xff0c;需要时调用就行了&#xff5e; 如图&#xff0c;创建一个带参函数&#xff0c;勾选"…

wxwidgets Ribbon构建多个page与按钮响应

新建一个控制台应用程序&#xff0c;添加好头文件的依赖与lib库文件的依赖&#xff0c;修改属性&#xff1a; 将进入ribbon界面的文件与主界面的类分开&#xff1a; 1、RibbonSample.cpp #include "stdafx.h" #include "MyFrame.h" class MyApp : public…

微服务——Docker

docker与虚拟机的区别 首先要知道三个层次 硬件层:计算机硬件 内核层:与硬件交互&#xff0c;提供操作硬件的指令 应用层: 系统应用封装内核指令为函数&#xff0c;便于程序员调用。用户程序基于系统函数库实现功能。 docker在打包的时候直接把应用层的函数库也进行打包&a…