sky-take-out项目Mybatis的使用
分页查询
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
- 是一个自定义的 查询参数封装类,通常包含如下字段:
@Datapublic 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
}
这样前端可以拿到:
- 总页数
- 当前页
- 每页数量
- 数据列表