侧边栏壁纸
博主头像
daixinmini的小屋博主等级

阿巴阿巴阿巴

  • 累计撰写 13 篇文章
  • 累计创建 4 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

深入理解 MyBatis 的 RowBounds 分页机制

380025303@qq.com
2025-11-11 / 0 评论 / 0 点赞 / 1 阅读 / 4384 字

什么是 RowBounds?

RowBounds 是 MyBatis 提供的逻辑分页工具类,用于控制查询结果的 偏移量(offset)每页条数(limit)

List<User> users = userMapper.selectAll(new RowBounds(10, 20));

上面的例子表示:从第 11 条记录开始,取 20 条。

RowBounds 的类定义简化如下:

public class RowBounds {
    public static final int NO_ROW_OFFSET = 0;
    public static final int NO_ROW_LIMIT = Integer.MAX_VALUE;

    private int offset;
    private int limit;

    public RowBounds(int offset, int limit) {
        this.offset = offset;
        this.limit = limit;
    }
}

RowBounds 的实现原理

关键点:RowBounds 不会修改 SQL,而是在内存中对查询结果进行截取。

也就是说:

  1. MyBatis 会先执行 SQL 查询,将所有符合条件的结果从数据库中取出。

  2. 然后在内存中,根据 offsetlimit 进行分页处理。

示意逻辑如下:

List<User> allUsers = queryAllUsersFromDB(); // 查询所有结果
List<User> pageUsers = allUsers.subList(offset, offset + limit); // 截取分页

因此,RowBounds 是内存分页,而不是数据库层面的分页。


RowBounds 的优缺点

优点

  • 简单易用,无需改动 SQL;

  • 对小数据量或缓存数据分页场景适用。

缺点

  • 无论查询第几页,都会把所有结果加载到内存,性能差;

  • 大数据量时,容易造成内存压力;

  • 数据库层索引无法充分利用。


如何实现高性能分页?

MyBatis 官方推荐在大数据量场景下,使用物理分页,即在 SQL 层面做分页。

1. 使用 PageHelper 插件

PageHelper.startPage(2, 10); // 第2页,每页10条
List<User> users = userMapper.selectAll();

生成 SQL:

SELECT * FROM user LIMIT 10 OFFSET 10;

2. 使用 MyBatis Plus 分页

IPage<User> page = new Page<>(2, 10);
IPage<User> result = userMapper.selectPage(page, null);

物理分页,性能更高。


源码层面的 RowBounds

在 MyBatis 的执行流程中:

  1. Executor 执行查询;

  2. 检测是否传入 RowBounds

  3. 查询完成后,在内存中处理结果集,跳过前 offset 条,只收集 limit 条。

源码片段(简化):

while (rs.next()) {
    if (rowBounds.getOffset() > count) continue;
    if (collected >= rowBounds.getLimit()) break;
    resultHandler.handleResult(row);
}

总结

分页方式

实现层级

是否改 SQL

性能

推荐使用

RowBounds

内存层

❌ 否

❌ 差

❌ 不推荐

PageHelper

SQL 层拦截

✅ 是

✅ 好

✅ 推荐

MyBatis Plus 分页

SQL 层拦截

✅ 是

✅ 好

✅ 推荐

一句话总结:
RowBounds 是 MyBatis 的逻辑分页工具,只在内存中截取结果,性能较差;大数据量场景应使用分页插件实现数据库层分页。

0
  • ${post.likes!0}

评论区