无处生还
76.43M · 2026-04-23
最近在帮几个朋友 review 毕业设计代码时,发现一个高频问题:
一查代码,果不其然——分页插件没注册。
这其实是个“经典陷阱”:MyBatis Plus(MP)的分页功能看似开箱即用,但如果你跳过了关键配置,它会静默退化为普通查询,既不报错,也不提醒,导致前端分页组件直接瘫痪。
今天,我就带大家从原理到实战,彻底搞懂 MP 分页的正确打开方式,并分享几个生产环境踩过的深坑。
传统分页你需要:
SELECT COUNT(*) FROM table WHERE ...SELECT * FROM table WHERE ... LIMIT offset, sizetotal、pages、current 等字段而 MP 只需一行:
java
编辑
IPage<Student> page = studentMapper.selectPage(new Page<>(1, 10), queryWrapper);
返回对象自动包含:
records:当前页数据列表total:总记录数(非当前页数量!)pages:总页数current / size:当前页码与每页大小前后端联调效率提升 50%+ ,尤其搭配 Vue/React 的分页组件时,几乎零转换成本。
关键点:必须使用 MybatisPlusInterceptor(MP 3.4.0+ 推荐方式)
java
编辑
@Configuration
@MapperScan("com.example.mapper") // 替换为你的 mapper 包路径
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusAdapter adapter = new MybatisPlusAdapter();
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 添加分页插件,指定数据库类型(必须!)
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
java
编辑
public IPage<Student> getPage(int current, int size, String name) {
Page<Student> page = new Page<>(current, size);
QueryWrapper<Student> qw = new QueryWrapper<>();
if (StringUtils.isNotBlank(name)) {
qw.like("name", name);
}
return studentMapper.selectPage(page, qw); // MP 自动注入 COUNT + 分页
}
java
编辑
@GetMapping("/students")
public ResponseEntity<IPage<Student>> list(
@RequestParam(defaultValue = "1") int current,
@RequestParam(defaultValue = "10") int size,
@RequestParam(required = false) String name) {
IPage<Student> page = studentService.getPage(current, size, name);
return ResponseEntity.ok(page);
}
前端(Vue3 + Element Plus)可直接消费:
js
编辑
const { records, total, current, size } = await api.getStudents({ current: 1, size: 10 });
// 直接绑定 el-pagination 的 total 和 currentPage
这是最常见问题。MP 在未注册插件时,selectPage 会退化为 selectList,只返回第一页数据,且 total=0。
验证方法:
启动日志中搜索 MybatisPlusInterceptor,确认是否加载成功。
如果你在 Mapper XML 中写了:
xml
编辑
<select id="selectPage">SELECT * FROM student WHERE ...</select>
MP 无法自动注入 COUNT 查询,因为 XML 覆盖了 MP 的默认行为。
解决方案:
QueryWrapper 构建动态 SQL@Select 注解 + MP 条件构造器使用 dynamic-datasource-spring-boot-starter 时,分页插件需在主数据源配置中注册,或通过 @DS 注解确保查询走正确数据源。
恶意请求 ?current=999999&size=10 会导致 LIMIT 9999990, 10,全表扫描拖垮数据库。
对策:
current <= 1000)if (current > 1000) throw new IllegalArgumentException("页码过大");对于千万级表,COUNT(*) 本身就很慢。
进阶方案:
WHERE id > lastId ORDER BY id LIMIT 10开启 MyBatis 日志,观察 MP 生成的 SQL 是否包含 COUNT 和 LIMIT:
sql
编辑
-- MP 自动生成的两条 SQL
SELECT COUNT(*) FROM student WHERE name LIKE '%张%';
SELECT * FROM student WHERE name LIKE '%张%' LIMIT 0, 10;
MyBatis Plus 的分页插件,是提升 CRUD 开发效率的利器。
但它不是“魔法”,需要你正确配置、理解原理、规避陷阱。
记住这个口诀:
把这篇文章加入书签,下次分页出问题,直接对照检查!
我是「不想打工的码农」,如果你觉得有收获,欢迎点赞、收藏、关注!