#踩雷问题记录 #MyBatis #分页查询 #Java

问题描述

在使用 MyBatis 搭配 PageHelper 分页插件时,接口请求 GET /aigc/app/query-apps?categoryId=1907635448432992257&pageNum=1&pageSize=6 本应返回6条记录,但实际返回了8条记录,pageSize 字段也变成了8。也就是说,分页功能未生效,多返回了数据。

经仔细检查,是因为mapper.xml中使用了比较复杂的联合查询逻辑,导致PageHelper插件失效。

原因分析

❗PageHelper 没有真正拦截分页 SQL

这类问题在使用 PageHelper + UNION ALL 的 SQL 时非常典型
PageHelper 会在 MyBatis 执行语句前拦截构造 SQL,自动添加 LIMIT。但如果你的 XML 中包含某些结构(如 UNION ALL、动态 SQL、复杂嵌套子查询),PageHelper 可能会提前查询完整数据(不分页),然后再进行内存分页(即 Java 代码中分页,而不是数据库分页)。

解决方式

询问了Gpt,尝试使用了”使用子查询包裹 UNION ALL,让 PageHelper 正确识别分页点“方式,未能成功解决。

最后采用的方式是手写分页查询,赋值给PageInfo。以下是文件的一些改动:

  1. mapper.xml : 在select结尾加上LIMIT和OFFSET
	LIMIT #{pageSize} OFFSET #{offset}
  1. xxxServiceImpl.java : 计算offset, total, 总页数,是否有上一页,是否有下一页等PageInfo信息
// PageHelper.startPage(pageNum, pageSize);   之前的PageHelper已经失效 
int offset = (pageNum - 1) * pageSize;  
  
List<AigcAppWithCategoryDTO> list = aigcAppMapper.selectAppsWithCategoryByCategoryId(categoryId,offset, pageSize);
PageInfo<AigcAppWithCategoryDTO> pageInfo = new PageInfo<>();  
pageInfo.setList(list);  
pageInfo.setPageNum(pageNum);  
pageInfo.setPageSize(pageSize);  
pageInfo.setTotal(total);  
pageInfo.setPages((total + pageSize - 1) / pageSize); // 计算总页数  
pageInfo.setHasPreviousPage(pageNum > 1); // 是否有上一页  
pageInfo.setHasNextPage(pageNum < pageInfo.getPages()); // 是否有下一页  
  
return pageInfo;
	
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐