MyBatis实现分页全过程
作者:Java自学之旅
MyBatis分页有三种方式:手动SQL分页(性能高但需处理数据库差异)、RowBounds(简单但不推荐)、PageHelper分页插件(自动改写SQL,推荐生产环境),PageHelper适合百万级数据优化,是终极解决方案
下面我将详细讲解MyBatis实现分页的几种方式,通过通俗易懂的故事和代码示例帮助理解:
故事背景
假设我们经营一个"图书管理系统",数据库中有10万本图书。
当用户查看图书列表时,一次性加载所有数据会导致系统崩溃(就像把整个图书馆的书都堆在收银台上)。
这时就需要分页功能——每次只展示"一架子书"(如每页20本)。
一、MyBatis实现分页的三种方式
1.手动SQL分页(物理分页)
SELECT * FROM books LIMIT #{start}, #{pageSize}
原理:
直接在SQL中通过LIMIT
(MySQL)或ROWNUM
(Oracle)控制数据范围。
代码示例:
// Mapper接口 List<Book> getBooksByPage(@Param("start") int start, @Param("pageSize") int pageSize); // 调用方式(获取第3页,每页20条) int pageNum = 3; int pageSize = 20; List<Book> books = bookMapper.getBooksByPage((pageNum-1)*pageSize, pageSize);
✅ 优点:
- 性能最佳(数据库只返回所需数据)
- 完全掌控SQL逻辑
❌ 缺点:
- 需手动计算偏移量(如
(pageNum-1)*pageSize
) - 不同数据库语法不同(MySQL用LIMIT,Oracle用ROWNUM)
2.RowBounds分页(逻辑分页)
RowBounds rowBounds = new RowBounds(40, 20); // 跳过前40条,取20条 List<Book> books = sqlSession.selectList("getAllBooks", null, rowBounds);
原理:
先查询所有数据到内存,再在Java层截取指定范围(像把整个图书馆的书运到仓库,再挑出20本)。
✅ 优点:
- 使用简单,无需改SQL
❌ 缺点:
- 性能灾难(数据量大时内存溢出)
- 实际工作中禁止使用!
3.分页插件(推荐方案)
使用PageHelper插件(最主流方案):
// 只需在查询前设置分页参数 PageHelper.startPage(3, 20); // 第3页,每页20条 List<Book> books = bookMapper.selectAllBooks(); // 获取分页信息 PageInfo<Book> pageInfo = new PageInfo<>(books); System.out.println("总页数:" + pageInfo.getPages());
原理:
通过MyBatis拦截器自动改写SQL,添加LIMIT
语句(像有个智能机器人帮你从书架上拿指定范围的书)。
配置步骤:
- 添加依赖:
<dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.3.2</version> </dependency>
- 配置拦截器(mybatis-config.xml):
<plugins> <plugin interceptor="com.github.pagehelper.PageInterceptor"/> </plugins>
✅ 优点:
- 零侵入(不改动原SQL)
- 自动适配不同数据库
- 返回丰富分页信息(总页数/当前页等)
二、分页原理对比表
方式 | 性能 | 易用性 | 适用场景 |
---|---|---|---|
手动SQL分页 | ⭐⭐⭐⭐ | ⭐⭐ | 简单SQL,明确数据库类型 |
RowBounds | ⭐ | ⭐⭐⭐⭐ | 禁止生产使用 |
PageHelper | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | 99%的生产场景 |
三、总结
绝对避免使用RowBounds
逻辑分页(除非数据量极小)
简单场景可用手动SQL分页(需处理数据库差异)
PageHelper是终极解决方案:
- 自动生成分页SQL
- 统一不同数据库行为
- 返回完整分页元数据
百万级数据分页优化:
-- 使用索引覆盖优化 SELECT * FROM books WHERE id >= (SELECT id FROM books ORDER BY id LIMIT 1000000, 1) LIMIT 20
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。