FastExcel 实现数据分批次导入、导出

devtools/2025/2/28 20:52:51/

是基于 FastExcel 实现数据分批次导入和保存的完整解决方案,结合了高性能流式读取与分批处理机制:


一、环境准备

  1. 依赖配置

    <dependency><groupId>cn.idev.excel</groupId><artifactId>fastexcel</artifactId><version>1.1.0</version>
    </dependency>

  2. 配置文件调整
    application.yml 中增加上传文件大小限制(适用于大文件上传):

    java">spring:servlet:multipart:max-file-size: 500MBmax-request-size: 500MB


二、分批次导入实现

1. 实体类定义

使用 @ExcelProperty 注解映射 Excel 列:

java">@Data
public class DataEntity {@ExcelProperty("ID")private Long id;@ExcelProperty("名称")private String name;}

2. 自定义监听器(核心)

通过流式读取实现内存优化和分批次处理:

java">public class BatchImportListener extends AnalysisEventListener<DataEntity> {private static final int BATCH_SIZE = 10000; // 每批次处理量private List<DataEntity> batchList = new ArrayList<>();private final DataService dataService; // 数据服务类@Overridepublic void invoke(DataEntity data, AnalysisContext context) {batchList.add(data);if (batchList.size() >= BATCH_SIZE) {saveBatch(); // 达到批次阈值时保存batchList.clear();}}@Overridepublic void doAfterAllAnalysed(AnalysisContext context) {if (!batchList.isEmpty()) saveBatch(); // 处理剩余数据}private void saveBatch() {dataService.batchInsert(batchList); // 调用批量插入方法}
}

3. 控制器调用
java">@PostMapping("/import")
public String importExcel(@RequestParam("file") MultipartFile file) {FastExcel.read(file.getInputStream(), DataEntity.class, new BatchImportListener(dataService)).sheet().doRead();return "导入成功";
}


三、分批次导出实现

1. 流式写入避免 OOM,使用临时文件缓存模式
  1. 内存优化
    默认情况下(.inMemory(true)),所有数据会暂存到内存中,当导出超过 10万行 数据时,极易引发 OutOfMemoryError
    启用 .inMemory(false) 后,数据将写入 临时文件(默认在系统临时目录),内存仅保留索引信息。

  2. 稳定性保障
    适合处理百万级甚至千万级数据导出场景,内存占用始终保持在 50MB 以内(实测数据)。

java">public void exportLargeData(HttpServletResponse response, String fileName) {response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, StandardCharsets.UTF_8));try (ExcelWriter excelWriter = FastExcel.write(response.getOutputStream(), DataEntity.class).inMemory(false) // 关键配置:启用磁盘缓存.build()) {WriteSheet sheet = FastExcel.writerSheet("百万数据").build();int page = 1;while (true) {List<DataEntity> batch = dataService.getBatchData(page, 50000); // 每次查询5万条if (batch.isEmpty()) break;excelWriter.write(batch, sheet); // 分批写入临时文件log.info("已写入第 {} 批,累计 {} 条", page, page * 50000);page++;}} catch (IOException e) {throw new RuntimeException("导出失败", e);}
}
2.临时文件管理
  1. 文件位置
    临时文件路径格式:/tmp/fastexcel-cache-{UUID}.tmp(Linux/Mac)或 C:\Users\xxx\AppData\Local\Temp\fastexcel-cache-{UUID}.tmp(Windows)

  2. 自动清理
    FastExcel 在以下情况会自动删除临时文件:

    • 调用 ExcelWriter.close() 时
    • JVM 正常退出时
    • 可通过 excelWriter.cleanup() 手动强制清理


四、关键优化点

  1. 内存控制

    • 导出时使用 try-with-resources 确保资源释放 
  2. 性能提升

    • 数据库操作使用批量插入而非单条插入(速度提升 10 倍+)。
    • 导出时启用临时文件缓存模式(.inMemory(false))。
  3. 异常处理

    • 在监听器中添加事务边界管理,避免长事务问题。
    • 导出文件名添加时间戳防重复:fileName + System.currentTimeMillis() + ".xlsx"

五、注意事项

  1. 大文件处理时建议增加进度提示(如每批次打印日志) 
  2. 导出时若需追加数据,应复用同一个 ExcelWriter 对象 
  3. 事务注解 @Transactional 建议加在 Service 方法而非监听器 

http://www.ppmy.cn/devtools/163442.html

相关文章

P9420 [蓝桥杯 2023 国 B] 子 2023

P9420 [蓝桥杯 2023 国 B] 子 2023 题目 分析代码 题目 分析 刚拿到这道题&#xff0c;我大脑简单算了一下&#xff0c;这个值太大了&#xff0c;直观感觉就很难&#xff01;&#xff01; 但是&#xff0c;你仔仔细细的一看&#xff0c;先从最简单的第一步入手&#xff0c;再…

JWT+redis实现令牌刷新优化方案

令牌刷新优化方案的详细实现步骤&#xff1a; 1. 令牌服务层改造 1.1 JWT工具类增强 // JwtUtils.java 新增方法 public class JwtUtils {// 生成带动态过期时间的令牌public static String createToken(String subject, String userId, String username, long expirationMi…

20250227解决飞凌OK3588-C的linux R4通过adb拷贝文件速度过慢的问题

20250227解决飞凌OK3588-C的linux R4通过adb拷贝文件速度过慢的问题 2025/2/27 16:51 缘起&#xff1a;最近测试OK3588-C的最新的R1版本的SDK&#xff0c;adb pull的速度为28.8 MB/s Z:\version\OK3588-C_Linux5.10.209Qt5.15.10_用户资料_R1 我司使用4线的USB2.0&#xff0c;…

ERROR:This version of pnpm requires at least Node.js vXXX 的解决方案

This version of pnpm requires at least Node.js vXXX 的解决方案 Centos7环境下&#xff0c;pnpm与Node.js版本不兼容导致报错 This version of pnpm requires at least Node.js vXXX 的解决方案 错误原因其实就是 pnpm 的版本不兼容 Node.js 的版本&#xff0c;明白了可以…

HOW POWERFUL ARE GRAPH NEURAL NETWORKS?(GIN)

GIN——Graph Isomorphism Network normal message deliverer related work GraphSAGE(Inductive Representation Learning on Large Graphs) 突破传统基于矩阵分解的节点嵌入方式&#xff0c;GraphSAGE 通过采样和聚合节点局部邻域的特征信息来生成嵌入&#xff0c;同时学习…

阿里云ECS通用计算

阿里云ECS通用计算概述 阿里云ECS&#xff08;Elastic Compute Service&#xff09;是阿里云提供的一款灵活、高效的云计算服务&#xff0c;它允许用户在云端部署虚拟计算实例&#xff0c;进行各种计算任务。通用计算型实例是阿里云ECS实例的一种类型&#xff0c;专门为中低负…

【备份】php项目处理跨域请求踩坑

这都是老生常谈的东西了。我还在踩坑&#xff0c;记录一下。 我在项目入口明明写了如下代码&#xff1a; // 处理预检请求 (OPTIONS) if ($_SERVER[REQUEST_METHOD] OPTIONS) {header("Access-Control-Allow-Origin: https://xxx.vip");header("Access-Cont…

redis批量删除namespace下的数据

在开发中为了更好的管理数据&#xff0c;对redis进行了分组存储操作&#xff0c;在存值时加了命名空间来实现&#xff0c;如下&#xff1a;Cacheable的value来实现分组 Cacheable(value "config",key "#comparamid_#comCode" )/* */ Query(value "…