java大批量数据导出excel

大批量数据导出,如果一次性查询出数据,会导致内存溢出,
这里的思路就是 分页查询出数据 依次写入表格中。上代码吧

用的是阿里的easyExcel

		<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>2.0.5</version>
        </dependency>
        <!--分页插件-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.3.0</version>
        </dependency>

导出excel实体

package com.chao.entity;

import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import lombok.Data;
import lombok.EqualsAndHashCode;

import java.util.Date;

/**
 * @author zhangcj
 * @date 2023/7/1 15:07
 */
@Data
@EqualsAndHashCode
public class User {

    @ExcelProperty("用户ID")
    private Long id;

    @ExcelProperty("名称")
    private String name;

    @ExcelProperty("年龄")
    private Integer age;

    @ExcelProperty("生日")
    @DateTimeFormat("yyyy年MM月dd日")
    private Date birthday;

}

controller

package com.chao.controller;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.chao.dao.UserDao;
import com.chao.entity.ExcelConstant;
import com.chao.entity.User;
import com.github.pagehelper.PageHelper;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.util.List;

/**
 * @author zhangcj
 * @date 2023/7/6 17:23
 */
@RequestMapping("user")
public class ExportExcelControllerV2 {

    @Resource
    UserDao userDao;

    @RequestMapping(value = "exportUserExcelV2",
            produces = {MediaType.MULTIPART_FORM_DATA_VALUE})
    public void exportUserExcelV2(@RequestBody User user, HttpServletResponse response) throws Exception {
        ExcelWriter excelWriter = null;
        ServletOutputStream out = null;
        try {
            out = response.getOutputStream();
            String fileName =  "repeatedWrite" + System.currentTimeMillis() + ".xlsx";
            excelWriter = EasyExcel.write(out, User.class).build();

            //  查询总数并封装相关变量(这块直接拷贝就行了不要改)
            Integer totalRowCount = this.userDao.getCount(user);
            Integer perSheetRowCount = ExcelConstant.PER_SHEET_ROW_COUNT;
            Integer pageSize = ExcelConstant.PER_WRITE_ROW_COUNT;
            Integer sheetCount = totalRowCount % perSheetRowCount == 0 ? (totalRowCount / perSheetRowCount) : (totalRowCount / perSheetRowCount + 1);
            Integer previousSheetWriteCount = perSheetRowCount / pageSize;
            Integer lastSheetWriteCount = totalRowCount % perSheetRowCount == 0 ?
                    previousSheetWriteCount :
                    (totalRowCount % perSheetRowCount % pageSize == 0 ? totalRowCount % perSheetRowCount / pageSize : (totalRowCount % perSheetRowCount / pageSize + 1));

            for (int i = 0; i < sheetCount; i++) {
                //  创建SHEET
                WriteSheet writeSheet = EasyExcel.writerSheet("sheet"+i).build();

                //  写数据  这个j的最大值判断直接拷贝就行了,不要改动
                for (int j = 0; j < (i != sheetCount - 1 ? previousSheetWriteCount : lastSheetWriteCount); j++) {
                    //  此处查询并封装数据即可  currentPage,  pageSize这俩个变量封装好的  不要改动
                    PageHelper.startPage(j + 1 + previousSheetWriteCount * i, pageSize);
                    List<User> userList = this.userDao.findList(user);
                    excelWriter.write(userList, writeSheet);
                }
            }

            //  下载EXCEL
            response.setHeader("Content-Disposition", "attachment;filename=" + new String((fileName).getBytes("gb2312"), "ISO-8859-1"));
            response.setContentType("multipart/form-data");
            response.setCharacterEncoding("utf-8");

            excelWriter.finish();


        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

    }
    
}

参数配置项

package com.chao.entity;

/**
 *
 * 优化加到配置文件中
 * @author zhangcj
 * @date 2023/7/1 15:58
 */
public class ExcelConstant {

    /**
     * 每个sheet存储的记录数  100W
     */
    public static final Integer PER_SHEET_ROW_COUNT = 1000000;

    /**
     * 每次向EXCEL写入的记录数(查询每页数据大小)  20W
     */
    public static final Integer PER_WRITE_ROW_COUNT = 50000;


}

可以调整 分页查询数量大小来调整最优的响应时间
我本地测试13万条数据 3s左右
在这里插入图片描述

如果有什么地方错了还麻烦各位帮忙指正

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java中进行大批量导出Excel时,可能会遇到内存溢出的问题。这是因为Excel文件通常占用较大的内存空间,当数据较大时,可能会超过JVM所分配的内存限制。 为了解决这个问题,可以采取以下几种方法: 1. 分批次导出:将要导出数据分成多个批次进行导出,每次导出一部分数据,以减少内存占用。可以根据数据的大小和服务器的内存情况来确定每个批次的大小。 2. 使用XSSFWorkbook替代HSSFWorkbook:HSSFWorkbook是用于处理Excel 97-2003格式的库,而XSSFWorkbook则是处理Excel 2007及更高版本的库。后者的内存占用要比前者低,因此可以考虑将工作簿对象由HSSFWorkbook替换为XSSFWorkbook。 3. 使用SXSSFWorkbook:SXSSFWorkbook是Apache POI提供的一种特殊的工作簿对象,它可以将数据直接写入磁盘而不是内存,从而大大降低内存占用。使用SXSSFWorkbook需要注意的是,导出Excel文件不能被随机访问,只能顺序读取。 4. 增加JVM内存限制:可以通过增加JVM的堆内存限制来解决内存溢出问题。可以通过修改JVM启动参数中的-Xmx和-Xms来增加堆内存限制。但是这种方法需要根据服务器的硬件资源和其他应用的内存需求进行合理的配置和调优。 5. 使用CSV格式代替Excel:如果Excel格式并不是必须要求,可以考虑将数据导出为CSV格式。CSV格式的文件较小,占用较少的内存,并且可以直接用文本编辑器打开和编辑。 以上是解决Java大批量导出Excel内存溢出问题的几种方法,可以根据具体情况选择适合的方法进行解决。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值