分页查询
public PageResult pageQuery(CategoryPageQueryDTO categoryPageQueryDTO) {
PageHelper.startPage(categoryPageQueryDTO.getPage(),categoryPageQueryDTO.getPageSize());
//下一条sql进行分页,自动加入limit关键字分页
Page<Category> page = categoryMapper.pageQuery(categoryPageQueryDTO);
return new PageResult(page.getTotal(), page.getResult());
}
这段 Java 代码是一个典型的 分页查询方法,使用了 PageHelper(MyBatis 的分页插件)和 MyBatis 的 Mapper 接口 来实现分页查询功能。
🧩 一、代码逐行解析
public PageResult pageQuery(CategoryPageQueryDTO categoryPageQueryDTO) {
- 定义一个名为
pageQuery
的方法,接收一个CategoryPageQueryDTO
类型的参数,返回值为PageResult
。 CategoryPageQueryDTO
是封装分页查询参数的 数据传输对象(DTO)。PageResult
是一个封装了分页结果(总记录数和当前页数据)的响应对象。
PageHelper.startPage(categoryPageQueryDTO.getPage(), categoryPageQueryDTO.getPageSize());
- 这是 PageHelper 提供的静态方法,用于开启分页功能。
- 它会拦截下一条 SQL 查询,并自动为其加上分页语句(如
LIMIT offset, pageSize
)。 - 参数说明:
getPage()
:当前页码(如第1页、第2页)getPageSize()
:每页显示的记录数
⚠️ 注意:
PageHelper.startPage()
只对紧随其后的第一条查询语句生效,所以一定要确保它在执行查询前调用。
Page<Category> page = categoryMapper.pageQuery(categoryPageQueryDTO);
- 调用
categoryMapper
的pageQuery
方法执行数据库查询。 - 返回值类型是
Page<Category>
,这是 PageHelper 提供的一个分页对象,内部封装了:- 当前页的数据(
List<Category>
) - 总记录数(
total
) - 当前页码、每页大小等信息(PageHelper 内部使用)
- 当前页的数据(
return new PageResult(page.getTotal(), page.getResult());
- 构造一个
PageResult
对象返回给前端:page.getTotal()
:总记录数page.getResult()
:当前页的数据列表(List<Category>
)
🧾 二、涉及类说明
1. PageHelper.startPage(...)
(MyBatis 分页插件)
- 来自:
com.github.pagehelper.PageHelper
- 功能:开启分页,自动为下一条 SQL 添加分页逻辑。
- 依赖:需要在项目中引入
pagehelper-spring-boot-starter
或手动配置插件。
2. Page<T>
(MyBatis 分页结果对象)
- 来自:
com.github.pagehelper.Page
- 是一个
List<T>
的子类,额外封装了分页信息,如:long getTotal()
:总记录数int getPageNum()
:当前页码int getPageSize()
:每页大小
3. CategoryPageQueryDTO
- 是一个自定义的 查询参数封装类,通常包含如下字段:
@Data public class CategoryPageQueryDTO implements Serializable { //页码 private int page; //每页记录数 private int pageSize; //分类名称 private String name; //分类类型 1菜品分类 2套餐分类 private Integer type; }
4. PageResult
- 是一个通用的分页结果封装类,通常用于返回给前端,结构如下:
@Data @AllArgsConstructor @NoArgsConstructor public class PageResult { private long total; // 总记录数 private List<?> records; // 当前页数据 }
📌 三、MyBatis Mapper 接口示例
public interface CategoryMapper {
Page<Category> pageQuery(CategoryPageQueryDTO categoryPageQueryDTO);
}
对应的 XML SQL 示例:
<!-- 分页查询-->
<select id="pageQuery" resultType="com.sky.entity.Category">
select * from category
<where>
<if test="name != null and name != ''">
and name like concat('%',#{name},'%')
</if>
<if test="type != null">
and type = #{type}
</if>
</where>
order by sort asc , create_time desc
</select>
✅ 四、总结流程图
1. 接口接收分页参数 (Page, PageSize)
↓
2. 调用 PageHelper.startPage(page, pageSize)
↓
3. 执行 categoryMapper.pageQuery(dto) 查询
↓
4. MyBatis + PageHelper 自动添加 LIMIT 分页语句
↓
5. 查询结果返回 Page<Category> 对象
↓
6. 构造 PageResult 返回给前端
✅ 五、注意事项
PageHelper 仅对下一条 SQL 生效
- 如果中间有其他 SQL 被执行,分页可能失效。
- 例如:在
startPage()
后又执行了select count(*)
,再执行主查询,可能导致分页失效。
不要在循环中使用 PageHelper
- 可能导致分页混乱。
PageHelper 与 MyBatis Plus 的 Page 对象不同
- MyBatis Plus 使用
IPage
,PageHelper 使用Page
,注意不要混淆。
- MyBatis Plus 使用
✅ 六、推荐优化:使用 PageResult 封装更丰富的信息
public class PageResult {
private long total;
private int pageNum;
private int pageSize;
private int totalPages;
private List<?> records;
public PageResult(long total, List<?> records, int pageNum, int pageSize) {
this.total = total;
this.records = records;
this.pageNum = pageNum;
this.pageSize = pageSize;
this.totalPages = (int) Math.ceil((double) total / pageSize);
}
// Getter / Setter
}
这样前端可以拿到:
- 总页数
- 当前页
- 每页数量
- 数据列表