【SpringBoot】整體下載大文件與分批下載大文件(利用MySql數據庫的Limit實現)


前文里談過一次性從數據庫取一個大結果集有可能導致outofMemory,當時的想法是分批去取回來,今天把它實現了,特地把代碼分享出來:

工程下載:https://files.cnblogs.com/files/xiandedanteng/CsvDownload20191027.rar

 生成CSV文件的三個不同函數

package com.hy.csvdld.util;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.List;

import org.apache.log4j.Logger;

import com.hy.csvdld.Entity.Emp;
import com.hy.csvdld.service.EmpService;

// 用於生成CSV文件
public class CsvMaker {
    private static Logger log = Logger.getLogger(CsvMaker.class);
    
    public void makeTenCsv(File file, EmpService empService) {
        try {
            List<Emp> emps = empService.selectTenEmp();

            FileWriter fileWriter = new FileWriter(file, true);

            int index = 0;
            for (Emp emp:emps) {
                index++;

                String info =""+index+","+ emp.asCsvLine()+ System.getProperty("line.separator");
                fileWriter.write(info);
            }

            fileWriter.flush();
            fileWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
   // 整體下載方案
public void makeManyCsv(File file, EmpService empService,int count) { try { List<Emp> emps = empService.selectMany(count); FileWriter fileWriter = new FileWriter(file, true); int index = 0; for (Emp emp:emps) { index++; String info =""+index+","+ emp.asCsvLine()+ System.getProperty("line.separator"); fileWriter.write(info); } fileWriter.flush(); fileWriter.close(); } catch (IOException e) { e.printStackTrace(); } } // 當count過大時,分批下載 public void makePartialCsv(File file, EmpService empService,int count) { try { int PartialSize=10000; int times=count/PartialSize; for(int i=0;i<times;i++){ log.info("第"+i+"批次處理"); FileWriter fileWriter = new FileWriter(file, true); List<Emp> emps = empService.selectPartial(i*PartialSize, PartialSize); int index = i*PartialSize; for (Emp emp:emps) { index++; String info =""+index+","+ emp.asCsvLine()+ System.getProperty("line.separator"); fileWriter.write(info); } fileWriter.flush(); fileWriter.close(); } } catch (IOException e) { e.printStackTrace(); } } }

具體SQL實現:

<?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.hy.csvdld.dao.EmpMapper">

    <select id="selectTenEmp" resultType="com.hy.csvdld.Entity.Emp">
        select id,name,age,cdate as ctime from emp order by id limit 10
    </select>
    
   <!-- 一次性取夠 --> <select id="selectManyEmp" resultType="com.hy.csvdld.Entity.Emp"> select id,name,age,cdate as ctime from emp order by id limit #{count} </select>
<!-- 分批多次取 --> <select id="selectPartialEmp" resultType="com.hy.csvdld.Entity.Emp"> select id,name,age,cdate as ctime from emp order by id limit #{start},#{size} </select> </mapper>

程序的優化,歸根結底是兩條路:空間換時間 或是 時間換空間,本文的分批取做法,是時間換空間的路數。

--END-- 2019年10月27日16:06:54

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM