如何为自定义JPA原生查询添加正确的分页功能?
自定义JPA原生查询分页的正确实现方案
问题根因
你的代码存在3个核心错误导致查询返回空:
PageRequest的页码默认从0开始计数,你前端传入的页码是1,对应查询的是偏移量为10的第二页数据,如果总数据不足10条自然返回空- 原生SQL查询返回
Page类型时,必须显式指定countQuery统计总条数,否则JPA无法正确计算分页参数 - Service层代码笔误用了
agentRepository,而非你定义的HeroRepository,同时SUM字段未指定别名无法和IHero接口映射
修复步骤
1. 修正Repository层代码
给@Query注解补充countQuery属性,给求和字段指定和IHero匹配的别名,调整分页占位符写法提升兼容性:
public interface HeroRepository extends JpaRepository<Hero,Long>{ @Query( value = "SELECT h.heroname , SUM(h.killCount) AS killcount FROM Heroes AS h GROUP BY h.heroname ORDER BY h.heroname ?#{#pageable}", countQuery = "SELECT COUNT(*) FROM (SELECT h.heroname FROM Heroes AS h GROUP BY h.heroname) temp", nativeQuery = true ) Page<IHero> findAllHeroByGroupName(Pageable pageable); }
2. 修正Service层代码
- 修正Repository注入的变量名
- 把传入的页码减1,适配
PageRequest0起始的规则
public Page<IHero> findAllHeroByGroupName(int pageNum) { // 页码减1处理,适配Spring Data 0起始的页码规则 Pageable pageable = PageRequest.of(pageNum - 1, 10); return heroRepository.findAllHeroByGroupName(pageable); }
3. 可选优化:修正Controller日志代码
你当前打印的是全局变量heroList的长度,而非查询返回的分页数据长度,建议修改日志方便排查:
@GetMapping("/heropage/{pageNum}") public String viewHeroPage(Model model, @PathVariable(name = "pageNum") int pageNum) { Page<IHero> page = heroService.findAllHeroByGroupName(pageNum); // 打印实际查询到的分页数据长度 System.out.println("查询到的英雄列表长度:" + page.getContent().size()); model.addAttribute("currentPage", pageNum); model.addAttribute("totalPages", page.getTotalPages()); model.addAttribute("totalItems", page.getTotalElements()); model.addAttribute("heroList", page.getContent() ); return "heropage"; }
修改后即可正常返回分页数据,原有非分页查询的逻辑不受影响。
内容的提问来源于stack exchange,提问作者Joona Ritva
相关产品推荐
相关产品推荐

