您现在的位置是:烟消火灭网 > 综合

mybatisplus分页查询

烟消火灭网2026-10-17 07:48:37【综合】4人已围观

简介 MyBatis Plus 的分页插件,说穿了就是帮你把那条 `LIMIT ? , ?` 给拼上。但就这么个拼 SQL 的动作,坑了我整整一个下午。那天排查线上慢查询,发现某个列表接口每页返回 20

MyBatis Plus 的页查分页插件,说穿了就是页查帮你把那条 `LIMIT ? , ?` 给拼上。但就这么个拼 SQL 的页查动作,坑了我整整一个下午。页查那天排查线上慢查询,页查发现某个列表接口每页返回 20 条,页查却把全表 10 万行都捞进了内存——代码里确实调了 `Page` 对象,页查可 `IPage` 的页查 `records` 字段装满了所有数据。翻到底层才发现,页查拦截器压根没注册。页查

配置分页插件这事儿,页查Spring Boot 环境下就三行代码。页查`MybatisPlusInterceptor` 得手动 new 出来,页查再往里塞一个 `PaginationInnerInterceptor`。页查有个细节特别容易忽略:如果你用了多数据源,页查每个 `SqlSessionFactory` 都得单独配这个拦截器,不然某个数据源的分页就是摆设。我见过有人把插件配在 `@Bean` 方法里,结果被 Spring 容器创建了两份实例,导致分页 SQL 被重复改写,那个报错信息能把你绕晕。

真正干活的时候,`Page` 构造器有两个参数:当前页和每页条数。页数从 1 开始,你要是传 0 进去,MyBatis Plus 会默认按第 1 页处理,但千万别依赖这个行为——代码评审时同事会指着你的鼻子问这是不是 bug。更靠谱的写法是让前端传 `pageNum` 和 `pageSize`,后端做一层防御性校验,超过 100 条的请求直接截断,防止有人恶意刷接口把数据库拖垮。

分页查询返回的是 `IPage` 接口,实现类通常是 `Page`。很多人只取 `records` 列表,把 `total` 字段晾在一边。可前端分页组件要显示总页数,没这个值页码就渲染不全。这里有个性能取舍:MyBatis Plus 默认会执行一条 `COUNT(*)` 查询,如果表数据量上了千万级,这条 count 可能比主查询还慢。遇到这种场景,我建议手动写一个轻量级的 count 语句,只查主键或者干脆用近似值缓存起来。

联表查询时分页要格外小心。MyBatis Plus 的 `Page` 对象配合自定义 SQL 时,拦截器会自动在 SQL 末尾追加 `LIMIT`,可如果你的 SQL 里已经带了 `GROUP BY` 或者 `DISTINCT`,分页结果可能对不上总数。我处理过一个报表接口,分组后结果集只有 50 组,但 count 统计的是分组前的明细行数,返回给前端的数据直接错乱。解法是分页 SQL 和 count SQL 分开写,count 语句里把 `GROUP BY` 去掉,只统计分组数量。

最后说个实用技巧:分页参数别直接塞进 `Page` 对象再传给 mapper 方法。更好的习惯是单独写一个查询 DTO,里面包含 `pageNum` 和 `pageSize` 字段,然后用 `Page page = new Page<>(dto.getPageNum(), dto.getPageSize())` 显式构造。这样单元测试时你可以直接 mock 这个 DTO,不用费劲去构造 `Page` 对象。还有,分页查询结果如果要做二次处理,比如给每条记录补充额外字段,记得在循环里用流式处理,别在 `records` 上反复调用 `getById` 这种逐条查库的操作——那会让你辛辛苦苦省下来的分页性能瞬间归零。

很赞哦!(2725)