某天,实习同学小陈接到一个需求:给用户列表加上分页功能。他信心满满地写下SQL:
SELECT * FROM user LIMIT 10 OFFSET 0; -- 第1页
SELECT * FROM user LIMIT 10 OFFSED 10; -- 第2页(拼写错误!)
结果第二页直接报错,用户数据乱成一锅粥!更糟糕的是,当数据量达到百万级时,手动计算总数导致接口超时…… 直到他发现了 PageHelper,从此分页如丝般顺滑,一行SQL都不用改!
核心定位:MyBatis的物理分页插件,自动将简单的Java方法调用转换为分页SQL。
核心优势:
com.github.pagehelper
pagehelper-spring-boot-starter
2.1.0
YAML
pagehelper:
helper-dialect: mysql # 数据库方言
reasonable: true # 分页合理化(页码溢出时自动修正)
support-methods-arguments: true
@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);
}
}
效果:
JSON
{
"total": 100,
"pageNum": 2,
"pageSize": 5,
"list": [...],
"hasNextPage": true
}
方法/类 | 说明 |
---|---|
PageHelper.startPage() | 开启分页(必须在查询前调用!) |
PageInfo |
分页结果包装类,包含总条数、页码等信息 |
Page |
继承ArrayList的分页对象,可直接返回 |
PageHelper.startPage(1, 10, false); // 第三个参数:不执行count查询
List users = userMapper.selectAll();
PageInfo pageInfo = new PageInfo<>(users);
pageInfo.setTotal(1000L); // 手动设置总数(比如从缓存获取)
@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语句
特性 | PageHelper | MyBatis-Plus |
---|---|---|
集成难度 | 简单,独立插件 | 需引入MP完整依赖 |
分页方式 | 基于拦截器,侵入性低 | 基于接口+分页模型 |
复杂SQL | 支持更好(尤其是多表查询) | 需要自定义XML或SQL |
性能 | 自动优化COUNT查询 | 需要手动优化 |
PageHelper.startPage(1, 10)
.setOrderBy("create_time DESC"); // 自动添加ORDER BY
List users = userMapper.selectAll();
PageHelper.startPage(1, 1000);
try (Cursor cursor = userMapper.scanAll()) {
cursor.forEach(user -> process(user));
}
PageHelper.startPage(1, 1000);
try (Cursor cursor = userMapper.scanAll()) {
cursor.forEach(user -> process(user));
}
互动话题:你在分页功能上踩过哪些坑?或者有没有更骚气的分页技巧?评论区见!