mybatis plus 分页(超详细)
💡一则或许对你有用的小广告
欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于
Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...
,点击查看项目介绍 ;- 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;
截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2900+ 小伙伴加入学习 ,欢迎点击围观
在现代 Web 开发中,分页功能是数据展示的核心需求之一。无论是用户浏览商品列表、查看文章列表,还是处理后台数据管理,分页都能有效提升用户体验和系统性能。MyBatis Plus 作为简化 MyBatis 使用的增强工具包,其内置的分页功能不仅操作简洁,还提供了丰富的扩展性。本文将从基础用法到进阶技巧,结合具体案例,深入讲解如何高效实现 mybatis plus 分页,帮助开发者快速掌握这一实用功能。
分页的基本概念与核心思想
分页的原理类似于图书馆管理书籍的方式:将大量书籍按每层书架存放固定数量的书籍,并通过书架编号快速定位目标书籍。在数据库中,分页通过 limit
和 offset
实现,其中:
- limit:指定每页显示的记录数量;
- offset:指定从第几条记录开始读取。
例如,第 2 页、每页显示 10 条记录的 SQL 语句为:
SELECT * FROM user LIMIT 10 OFFSET 10;
MyBatis Plus 将这一过程封装为更简洁的 API,开发者无需手动拼接 SQL,只需通过 Page
对象即可实现分页查询。
MyBatis Plus 分页的核心类与基础用法
Page 对象的创建与配置
Page
是 MyBatis Plus 分页功能的核心类,用于存储分页参数和结果。其构造方法接受两个参数:current
(当前页码)和 size
(每页数量)。例如:
Page<User> page = new Page<>(1, 10);
此外,Page
还支持自定义参数,例如设置是否需要统计总记录数(count
)或排序方式。
基础分页查询实现
通过 BaseMapper
的 selectPage
方法,可以快速实现分页查询。以下是一个简单示例:
// 1. 创建分页对象
Page<User> page = new Page<>(1, 10);
// 2. 执行分页查询
IPage<User> result = userMapper.selectPage(page, new QueryWrapper<User>().eq("status", 1));
// 3. 获取分页结果
List<User> records = result.getRecords();
long total = result.getTotal();
此示例展示了如何查询状态为 1
的用户,并返回第一页的 10 条记录。
分页查询的高级技巧与场景适配
自定义分页逻辑与排序
在实际开发中,可能需要根据业务需求自定义排序规则或分页条件。例如,按用户注册时间倒序排列:
Page<User> page = new Page<>(1, 10);
page.addOrderDesc("create_time");
IPage<User> result = userMapper.selectPage(page, new QueryWrapper<User>().ne("role", "admin"));
通过 addOrderDesc
或 addOrderAsc
方法,可以灵活控制排序方向。
嵌套查询与复杂条件的分页处理
当查询条件涉及关联表或聚合函数时,需注意 MyBatis Plus 的分页逻辑可能与原始 SQL 存在差异。例如,若需分页统计订单金额:
// 方式一:使用原生 SQL
String sql = "SELECT user_id, SUM(amount) AS total FROM orders GROUP BY user_id";
Page<User> page = new Page<>(1, 10);
IPage<User> result = userMapper.selectPage(page, new NativeSqlWrapper(sql));
// 方式二:通过自定义 SQL
@Select("SELECT * FROM user WHERE id IN (SELECT user_id FROM orders GROUP BY user_id HAVING COUNT(*) > 5)")
Page<User> findActiveUsers(Page<User> page);
此时需通过 NativeSqlWrapper
或直接编写 SQL 语句来适配复杂场景。
分页性能优化与常见问题解决
优化分页查询的性能
分页查询的性能瓶颈通常出现在大数据量场景下,尤其是当 offset
值较大时。例如,查询第 1000 页(offset = 9990
)可能导致数据库扫描大量记录。优化方法包括:
- 使用索引:为查询条件字段(如
status
、create_time
)添加索引; - 避免 N+1 查询:使用
selectPage
时确保关联查询通过JOIN
完成,而非在 Java 层循环查询; - 使用游标分页:通过字段值定位而非
offset
,例如:QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.gt("id", lastId).orderByAsc("id"); Page<User> page = new Page<>(1, 10);
常见问题与解决方案
- 分页统计不准确:
检查count
查询是否与分页 SQL 逻辑一致,或通过page.setSearchCount(false)
关闭统计(适用于总记录数无需精确的场景)。 - 分页参数丢失:
在 MyBatis XML 映射文件中,确保<select>
标签的resultType
和parameterType
正确配置。
分页功能的实战案例
场景:电商商品列表的分页展示
假设需要实现一个商品列表页面,要求按分类、价格区间筛选,并支持排序和分页。代码实现如下:
public IPage<Product> searchProducts(int current, int size, String category, BigDecimal minPrice, BigDecimal maxPrice) {
Page<Product> page = new Page<>(current, size);
QueryWrapper<Product> wrapper = new QueryWrapper<>();
wrapper.eq(category != null, "category", category);
wrapper.ge(minPrice != null, "price", minPrice);
wrapper.le(maxPrice != null, "price", maxPrice);
wrapper.orderByDesc("sales"); // 按销量排序
return productMapper.selectPage(page, wrapper);
}
此方法通过动态条件构造查询,并返回包含商品信息和分页数据的 IPage
对象。
场景:结合分页的统计报表
若需同时获取分页数据和统计信息(如总销售额),可通过自定义 SQL 实现:
@Select({
"<script>",
"SELECT p.*, SUM(o.amount) AS total_sales FROM product p",
"LEFT JOIN order_item o ON p.id = o.product_id",
"<where>",
"<if test='category != null'> AND p.category = #{category} </if>",
"</where>",
"GROUP BY p.id",
"ORDER BY total_sales DESC",
"LIMIT #{page.size} OFFSET #{page.offset}",
"</script>"
})
Page<ProductSales> getTopProductsByCategory(Page<ProductSales> page, @Param("category") String category);
通过 Page
对象传递分页参数,结合 SQL 的 GROUP BY
和 LIMIT
完成复杂报表的分页。
结论
MyBatis Plus 的分页功能通过简洁的 API 和灵活的扩展性,极大简化了开发者的分页实现流程。从基础的 selectPage
方法到复杂的动态查询与性能优化,开发者需根据业务场景选择合适方案。掌握分页的核心逻辑、善用 Page
对象的配置能力,并结合 SQL 优化技巧,能够显著提升系统的效率和用户体验。
通过本文的讲解,希望读者能够:
- 快速上手 MyBatis Plus 分页的基础用法;
- 理解分页在复杂场景下的实现逻辑;
- 掌握性能调优的关键方法。
分页功能虽看似简单,但其背后涉及数据库优化、代码设计等多方面知识。持续实践与探索,将帮助开发者更好地驾驭这一核心技术点。