news 2026/4/3 6:47:15

分批导出大文件:JPA Slice 使用解决page查询做导出时无效count问题

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
分批导出大文件:JPA Slice 使用解决page查询做导出时无效count问题

1.要重写底层readPage方法,删除掉count的部分

package com.konka.api.bms.repository; import com.konka.api.voucher.domain.SnView; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.support.JpaEntityInformation; import org.springframework.data.jpa.repository.support.SimpleJpaRepository; import org.springframework.stereotype.Repository; import javax.persistence.EntityManager; import javax.persistence.TypedQuery; import java.io.Serializable; import java.util.List; public class CustomNotCountRepository<T,ID extends Serializable> extends SimpleJpaRepository<T,ID> { public CustomNotCountRepository(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager) { super(entityInformation, entityManager); } public CustomNotCountRepository(Class<T> domainClass, EntityManager em) { super(domainClass, em); } @Override protected <S extends T> Page<S> readPage(TypedQuery<S> query, Class<S> domainClass, Pageable pageable, Specification<S> spec) { query.setFirstResult((int)pageable.getOffset()); query.setMaxResults(pageable.getPageSize()); List<S> content = query.getResultList(); return new PageImpl<>(content, pageable, content.size()); } }

2.封装slice查询方法

package com.konka.api.bms.repository; import com.konka.api.voucher.domain.SnView; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; import org.springframework.data.jpa.domain.Specification; import org.springframework.stereotype.Repository; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; @Repository public class HelperRepository<T>{ @PersistenceContext private EntityManager em; public <T> Slice<T> findAll(Specification<T> specification, Pageable pageable, Class<T> domainClass){ CustomNotCountRepository customNotCountRepository = new CustomNotCountRepository<>(domainClass, em); return customNotCountRepository.findAll(specification, pageable); } }

3.调用查询

spec = getSpec(searchData); pageable = Pageutil.getPageRequest(searchData); all = this.helperRepository.findAll(spec, pageable, SnView.class);

4.分批导出

@Async @Transactional(readOnly = true) public void pageForExportV2(PageParam<SnViewDTO> searchData, Authentication currentAuth) { SecurityUtils.buildAuthentication(currentAuth); Specification<SnView> spec; String entityName = "条码库存"; DownloadTaskCenterDTO taskCenterDTO = commonFeignService.saveDownloadTaskSimple("条码库存", entityName, entityName); Class<SnViewDTO> clazz = SnViewDTO.class; String fileName = entityName + "-" + DateUtil.umsNow() + ExcelTypeEnum.XLSX.getValue(); Path f = Paths.get(FileUtils.getCachePath(), fileName); ExcelWriter excelWriter = EasyExcel.write(f.toString(), clazz) .registerConverter(new LocalDateConverter()) .registerConverter(new LocalDateTimeConverter()) .registerConverter(new BooleanConverter()) // 注意:移除入参中的excelTemps,避免全量加载 .build(); WriteSheet sheet1 = EasyExcel.writerSheet("sheet1").build(); // 一次 EXPORT_BATCH_SIZE 条 searchData.setPageSize(EXPORT_BATCH_SIZE); int page = 1; Pageable pageable; Slice<SnView> all; try{ while (true) { spec = getSpec(searchData); pageable = Pageutil.getPageRequest(searchData); all = this.helperRepository.findAll(spec, pageable, SnView.class); if (!CollectionUtils.isEmpty(all.getContent())){ excelWriter.write(all.getContent(), sheet1); }else { break; } // 终止循环条件:当前批次无数据(说明已查询完所有数据) if (all.getContent().size() < EXPORT_BATCH_SIZE) { break; } searchData.setPageIndex(++page); } if (excelWriter != null) { excelWriter.finish(); log.info("Excel文件写入完成,已生成完整文件"); } FileInfoDTO fileInfo = commonFeignService.uploadFile(entityName, f); commonFeignService.updateDownloadTaskCenter(fileInfo.getId(), taskCenterDTO.getId(), null); }catch (Exception e){ // 全局异常捕获:所有步骤的异常均在此处理,更新任务为失败 log.error("条码库存导出失败,任务ID:{}", e.getMessage()); if (Objects.nonNull(taskCenterDTO)) { taskCenterDTO.setTaskArgs(e.getMessage()); commonFeignService.updateDownloadMsg(taskCenterDTO); } }finally { // ########################################################### // 关键修复2:finally块做**双重兜底**+资源释放,确保无遗漏 // ########################################################### try { // 兜底:若未主动执行finish,在此执行(防止异常导致主动finish未执行) if (excelWriter != null) { excelWriter.finish(); } } catch (Exception e) { log.error("ExcelWriter关闭失败", e); } try { // 删除临时Excel文件:无论成功/失败,都删除,避免临时文件堆积 if (f != null && Files.exists(f)) { Files.deleteIfExists(f); log.info("临时Excel文件已删除:{}", f); } } catch (IOException e) { log.error("删除临时Excel文件失败,文件路径:{}", f, e); } } }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/13 0:31:58

计算机Python毕设实战-基于Flask和Vue的电商管理系统商品管理、订单处理、用户运营和数据分析【完整源码+LW+部署说明+演示视频,全bao一条龙等】

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/4/2 21:17:44

vue+springboot在线调查问卷系统开题报告

目录系统背景与意义技术选型依据系统功能模块创新点分析预期成果项目技术支持可定制开发之功能亮点源码获取详细视频演示 &#xff1a;文章底部获取博主联系方式&#xff01;同行可合作系统背景与意义 在线调查问卷系统结合Vue.js前端框架与SpringBoot后端技术&#xff0c;旨在…

作者头像 李华
网站建设 2026/3/30 11:08:10

vue+springboot家教信息管理系统开题报告

目录 项目背景与意义技术选型系统功能模块创新点开发计划预期成果 项目技术支持可定制开发之功能亮点源码获取详细视频演示 &#xff1a;文章底部获取博主联系方式&#xff01;同行可合作 项目背景与意义 家教信息管理系统旨在整合家教资源&#xff0c;优化家长与教师之间的匹…

作者头像 李华
网站建设 2026/3/21 22:10:25

Python毕设项目推荐-基于python养老社区的查询预约系统实现在线预约、动态床位管理与个性化筛选功能【附源码+文档,调试定制服务】

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/3/27 14:23:10

vim 里按什么可以调到文件末尾?

核心快捷键及用法 在 Vim 中跳转到文件末尾主要有两种常用方式,核心是要确保先处于 普通模式(Normal Mode)(按 Esc 键即可切换到普通模式): 最快捷的方式:大写 G在普通模式下,直接按键盘上的 G(大写,无需按住 Shift 的话可以按 Shift+g),光标会瞬间跳转到文件的最…

作者头像 李华