Spring Boot中使用Pageable构造含嵌套列表的ResponseDto的高效方案问询
优化方案
你当前的实现存在典型的N+1查询问题:每次遍历Page元素都会单独发起一次数据库请求,总查询次数为1(查主Page)+ N(Page元素个数),数据量较大时性能损耗非常严重,可通过批量查询+内存匹配的方式将查询次数降到固定2次,大幅提升效率
具体实现步骤
- 第一步:查询得到主数据
Page<ResponseDto> - 第二步:提取Page中所有ResponseDto的关联字段
someProp值,去重后得到批量查询的参数集合 - 第三步:调用批量查询接口一次性拿到所有关联的
NestedDto,组装为key为someProp值、value为对应NestedDto列表的映射Map - 第四步:遍历Page中的ResponseDto元素,直接从Map中取出对应嵌套列表赋值,纯内存操作无额外IO开销
代码示例
// 1. 查询主记录分页数据 Page<ResponseDto> responsePage = repository.findRecord(); // 2. 提取所有关联键,去重减少无效查询 List<String> somePropList = responsePage.getContent().stream() .map(ResponseDto::getSomeProp) .distinct() .toList(); // 3. 批量查询所有嵌套数据,组装为映射Map // 需先在otherRepository中新增批量查询方法 Map<String, List<NestedDto>> nestedDtoMap = otherRepository.findNestedRecordBySomePropIn(somePropList) .stream() .collect(Collectors.groupingBy(NestedDto::getSomeProp)); // 4. 内存赋值,无数据库请求 for (ResponseDto dto : responsePage.getContent()) { dto.setNestedDto(nestedDtoMap.getOrDefault(dto.getSomeProp(), Collections.emptyList())); }
补充说明
需要先在
otherRepository中新增批量查询方法,若使用Spring Data JPA,按命名规则定义即可,无需手动编写SQL,方法签名参考:List<NestedDto> findNestedRecordBySomePropIn(List<String> somePropList);
如果你的业务场景允许主表和嵌套表做关联查询,也可以直接在主查询中通过关联查询一次性封装好嵌套字段,只需要1次数据库查询,性能更高。但如果两个表属于不同数据源、或者关联查询性能不如两次单表查询的场景,优先使用上述批量查询方案。
内容的提问来源于stack exchange,提问作者Frenk
相关产品推荐
相关产品推荐

