第11节:分页查询(MyBatis 实现分页,后端最常用功能)
知识点讲解
日常管理系统几乎都要分页:数据量大的时候,不能一次性把全部数据查出来,会占用内存、网络带宽。
分页核心两个参数:
pageNum:当前页码(第几页)pageSize:每页多少条数据
返回结果需要包含:总条数、总页数、当前页数据列表
示例:pageNum=1,pageSize=2 → 查询第 1 页,每页 2 条记录
两种分页方案:
- 原生 MyBatis 手写 SQL 分页(本次讲,底层 LIMIT),适合理解原理
- MyBatis-Plus 分页插件(后续拓展)
步骤 1:新建分页返回实体 PageResult.java
包路径:com.zzs.szyt.common
package com.zzs.szyt.common;
import lombok.Data;
import java.util.List;
/**
* 分页统一返回对象
*/
@Data
public class PageResult<T> {
// 当前页数据列表
private List<T> records;
// 总记录数
private Long total;
// 当前页码
private Integer pageNum;
// 每页条数
private Integer pageSize;
// 总页数
private Integer pages;
}
步骤 2:新建分页查询参数实体 PageQuery.java
包路径:com.zzs.szyt.common
package com.zzs.szyt.common;
import jakarta.validation.constraints.Min;
import lombok.Data;
/**
* 分页查询入参
*/
@Data
public class PageQuery {
@Min(value = 1, message = "页码不能小于1")
private Integer pageNum = 1; // 默认第1页
@Min(value = 1, message = "每页条数不能小于1")
private Integer pageSize = 2; // 默认每页2条
}
步骤 3:UserMapper 新增分页查询方法 + 统计总数方法
打开 UserMapper.java 接口,增加两个抽象方法:
/**
* 分页查询用户
* @param pageNum 页码
* @param pageSize 每页条数
* @return 用户列表
*/
List<User> selectUserPage(@Param("pageNum") Integer pageNum, @Param("pageSize") Integer pageSize);
/**
* 查询用户总数量
* @return 总条数
*/
Long selectUserCount();
⚠️
@Param注解:MyBatis 中把参数名字传给 XML 文件,不要漏
步骤 4:UserMapper.xml 增加分页 SQL 和统计 SQL
打开 resources/mapper/UserMapper.xml,新增两个标签
<!-- 分页查询 -->
<select id="selectUserPage" resultType="com.zzs.szyt.entity.User">
SELECT id,name,age FROM user
LIMIT #{pageNum}, #{pageSize}
</select>
<!-- 查询总记录数 -->
<select id="selectUserCount" resultType="java.lang.Long">
SELECT COUNT(*) FROM user
</select>
MySQL LIMIT 语法:
LIMIT offset,sizeoffset = (pageNum -1)*pageSize
注意!上面 XML 我写的 #{pageNum} 是偏移量,Controller 里要手动计算偏移量,不要直接传 pageNum 进去!
步骤 5:UserController 新增分页接口
/**
* 用户分页查询 GET /user/page
* @param pageQuery 分页参数
* @return 分页结果
*/
@GetMapping("/page")
public Result<PageResult<User>> userPage(@Valid PageQuery pageQuery){
// 1.计算偏移量 offset = (当前页码-1)*每页条数
int offset = (pageQuery.getPageNum() - 1) * pageQuery.getPageSize();
// 2.分页查询数据列表
List<User> userList = userMapper.selectUserPage(offset, pageQuery.getPageSize());
// 3.查询总条数
Long total = userMapper.selectUserCount();
// 4.组装分页返回对象
PageResult<User> pageResult = new PageResult<>();
pageResult.setRecords(userList);
pageResult.setTotal(total);
pageResult.setPageNum(pageQuery.getPageNum());
pageResult.setPageSize(pageQuery.getPageSize());
// 计算总页数 total / pageSize,向上取整
int pages = (int) Math.ceil((double)total / pageQuery.getPageSize());
pageResult.setPages(pages);
return Result.success(pageResult);
}
步骤 6:测试(Postman / 浏览器 GET 请求)
接口地址:http://localhost:8080/user/page?pageNum=1&pageSize=2
预期返回 JSON:
{
"code":200,
"msg":"操作成功",
"data":{
"records": [
{"id":1,"name":"张三","age":20},
{"id":2,"name":"李四","age":22}
],
"total":2,
"pageNum":1,
"pageSize":2,
"pages":1
}
}

多组测试场景
- 不传参数:
http://localhost:8080/user/page,自动使用默认 pageNum=1,pageSize=2 - pageNum 传 0:触发参数校验,返回
{"code":500,"msg":"页码不能小于1","data":null} - pageNum=1,pageSize=1:只返回第一条数据
拓展思考:分页接口也可以加上 Redis 缓存,你可以尝试自己加上,先完成基础分页测试。
任务
把上面代码依次新建 / 修改,重启项目,用浏览器或者 Postman 测试分页接口。