【MyBatis神器】PageHelper:分页从未如此优雅!

 开篇故事:一场“分页灾难”的救赎

某天,实习同学小陈接到一个需求:给用户列表加上分页功能。他信心满满地写下SQL:

SELECT * FROM user LIMIT 10 OFFSET 0;  -- 第1页
SELECT * FROM user LIMIT 10 OFFSED 10; -- 第2页(拼写错误!)

结果第二页直接报错,用户数据乱成一锅粥!更糟糕的是,当数据量达到百万级时,手动计算总数导致接口超时…… 直到他发现了 PageHelper,从此分页如丝般顺滑,一行SQL都不用改!


 第一幕:PageHelper是谁?

核心定位:MyBatis的物理分页插件,自动将简单的Java方法调用转换为分页SQL。
核心优势

  • 零侵入:不改动原有Mapper代码,只需添加几行配置。
  • 高效智能:自动处理分页逻辑和总条数统计。
  • 多数据库支持:MySQL、Oracle、PostgreSQL等“通吃”。

️ 第二幕:5分钟极速入门

1️⃣ 添加依赖


    com.github.pagehelper
    pagehelper-spring-boot-starter
    2.1.0

2️⃣ 配置参数(application.yml)

YAML

pagehelper:
  helper-dialect: mysql    # 数据库方言
  reasonable: true         # 分页合理化(页码溢出时自动修正)
  support-methods-arguments: true
3️⃣ 代码实战
@RestController
public class UserController {

    @Autowired
    private UserMapper userMapper;

    @GetMapping("/users")
    public PageInfo getUsers(@RequestParam int pageNum, 
                                   @RequestParam int pageSize) {
        // 魔法开始!紧跟的查询自动分页
        PageHelper.startPage(pageNum, pageSize);
        List users = userMapper.selectAll();  // 原SQL:SELECT * FROM user
        return new PageInfo<>(users);
    }
}

效果

  • 访问/users?pageNum=2&pageSize=5
  • 实际SQL:SELECT * FROM user LIMIT 5,5
  • 响应包含分页信息:

    JSON

    {
      "total": 100,
      "pageNum": 2,
      "pageSize": 5,
      "list": [...],
      "hasNextPage": true
    }
    

 第三幕:核心机制揭秘

1️⃣ 分页原理
【MyBatis神器】PageHelper:分页从未如此优雅!_第1张图片
2️⃣ 重要API
方法/类 说明
PageHelper.startPage() 开启分页(必须在查询调用!)
PageInfo 分页结果包装类,包含总条数、页码等信息
Page 继承ArrayList的分页对象,可直接返回

❗ 第四幕:避坑指南 & 高频问题

1️⃣ Q:分页失效了?
  • 检查点
    • PageHelper.startPage() 必须在查询方法前调用(中间不能有其它查询!)。
    • 确保没有在配置中漏掉 pagehelper.reasonable=true。
2️⃣ Q:统计总数慢怎么办?
  • 优化方案
    PageHelper.startPage(1, 10, false); // 第三个参数:不执行count查询
    List users = userMapper.selectAll();
    PageInfo pageInfo = new PageInfo<>(users);
    pageInfo.setTotal(1000L); // 手动设置总数(比如从缓存获取)
    
3️⃣ Q:多表联查分页错误?
  • 原因:多表查询时,自动生成的COUNT语句可能不正确。
  • 解决方案:自定义COUNT查询:
    @Select("SELECT * FROM user u LEFT JOIN dept d ON u.dept_id=d.id")
    List selectUserWithDept();
    
    // Service中调用
    PageHelper.startPage(pageNum, pageSize)
               .setCountSql("SELECT COUNT(*) FROM user"); // 手动指定COUNT语句
    
4️⃣ Q:与MyBatis-Plus的分页哪个更好?
特性 PageHelper MyBatis-Plus
集成难度 简单,独立插件 需引入MP完整依赖
分页方式 基于拦截器,侵入性低 基于接口+分页模型
复杂SQL 支持更好(尤其是多表查询) 需要自定义XML或SQL
性能 自动优化COUNT查询 需要手动优化

 第五幕:进阶技巧——玩转分页

1️⃣ 自定义排序字段
PageHelper.startPage(1, 10)
           .setOrderBy("create_time DESC");  // 自动添加ORDER BY
List users = userMapper.selectAll();
2️⃣ 分页+流式查询(大数据量)
PageHelper.startPage(1, 1000);
try (Cursor cursor = userMapper.scanAll()) {
    cursor.forEach(user -> process(user));
}
3️⃣ 配合AOP自动分页
PageHelper.startPage(1, 1000);
try (Cursor cursor = userMapper.scanAll()) {
    cursor.forEach(user -> process(user));
}

 总结:分页从未如此简单

  • PageHelper 是MyBatis生态的“分页终结者”,一行代码实现复杂分页。
  • 掌握常见避坑技巧,应对百万数据游刃有余。
  • 进阶玩法让分页更智能、更高效!

互动话题:你在分页功能上踩过哪些坑?或者有没有更骚气的分页技巧?评论区见!

你可能感兴趣的:(mybatis)