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 分页,帮助开发者快速掌握这一实用功能。


分页的基本概念与核心思想

分页的原理类似于图书馆管理书籍的方式:将大量书籍按每层书架存放固定数量的书籍,并通过书架编号快速定位目标书籍。在数据库中,分页通过 limitoffset 实现,其中:

  • 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)或排序方式。

基础分页查询实现

通过 BaseMapperselectPage 方法,可以快速实现分页查询。以下是一个简单示例:

// 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"));  

通过 addOrderDescaddOrderAsc 方法,可以灵活控制排序方向。

嵌套查询与复杂条件的分页处理

当查询条件涉及关联表或聚合函数时,需注意 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)可能导致数据库扫描大量记录。优化方法包括:

  1. 使用索引:为查询条件字段(如 statuscreate_time)添加索引;
  2. 避免 N+1 查询:使用 selectPage 时确保关联查询通过 JOIN 完成,而非在 Java 层循环查询;
  3. 使用游标分页:通过字段值定位而非 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> 标签的 resultTypeparameterType 正确配置。

分页功能的实战案例

场景:电商商品列表的分页展示

假设需要实现一个商品列表页面,要求按分类、价格区间筛选,并支持排序和分页。代码实现如下:

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 BYLIMIT 完成复杂报表的分页。


结论

MyBatis Plus 的分页功能通过简洁的 API 和灵活的扩展性,极大简化了开发者的分页实现流程。从基础的 selectPage 方法到复杂的动态查询与性能优化,开发者需根据业务场景选择合适方案。掌握分页的核心逻辑、善用 Page 对象的配置能力,并结合 SQL 优化技巧,能够显著提升系统的效率和用户体验。

通过本文的讲解,希望读者能够:

  1. 快速上手 MyBatis Plus 分页的基础用法;
  2. 理解分页在复杂场景下的实现逻辑;
  3. 掌握性能调优的关键方法。

分页功能虽看似简单,但其背后涉及数据库优化、代码设计等多方面知识。持续实践与探索,将帮助开发者更好地驾驭这一核心技术点。

最新发布