本文目录导读:

我来详细介绍 MyBatis 分页的几种实现方式:
物理分页(推荐) - 使用 PageHelper
Maven 依赖
<!-- PageHelper 分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.6</version>
</dependency>
配置 PageHelper
# application.yml pagehelper: helper-dialect: mysql reasonable: true support-methods-arguments: true params: count=countSql
Service 层实现
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
/**
* 分页查询用户
* @param pageNum 当前页码
* @param pageSize 每页条数
* @return 分页结果
*/
public PageInfo<User> getUserByPage(int pageNum, int pageSize) {
// 1. 设置分页参数
PageHelper.startPage(pageNum, pageSize);
// 2. 执行查询(MyBatis 会自动拦截并添加分页)
List<User> userList = userMapper.selectAll();
// 3. 包装分页信息
return new PageInfo<>(userList);
}
}
Mapper 接口
@Mapper
public interface UserMapper {
// 普通的查询方法,不需要手动处理分页
List<User> selectAll();
// 带条件的分页查询
List<User> selectByCondition(UserQuery query);
}
Mapper XML
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.UserMapper">
<!-- 普通查询,不需要LIMIT -->
<select id="selectAll" resultType="com.example.entity.User">
SELECT * FROM user ORDER BY id DESC
</select>
<!-- 带条件的分页查询 -->
<select id="selectByCondition" resultType="com.example.entity.User">
SELECT * FROM user
<where>
<if test="username != null and username != ''">
AND username LIKE CONCAT('%', #{username}, '%')
</if>
<if test="status != null">
AND status = #{status}
</if>
</where>
ORDER BY id DESC
</select>
</mapper>
Controller 层
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/page")
public Result<PageInfo<User>> getUserPage(
@RequestParam(defaultValue = "1") int pageNum,
@RequestParam(defaultValue = "10") int pageSize) {
PageInfo<User> pageInfo = userService.getUserByPage(pageNum, pageSize);
return Result.success(pageInfo);
}
}
前端接收的分页数据格式
{
"code": 200,
"message": "success",
"data": {
"pageNum": 1, // 当前页码
"pageSize": 10, // 每页条数
"size": 10, // 当前页数据条数
"total": 100, // 总记录数
"pages": 10, // 总页数
"list": [ // 数据列表
{
"id": 1,
"username": "张三",
"email": "zhangsan@example.com"
}
],
"isFirstPage": true, // 是否为第一页
"isLastPage": false, // 是否为最后一页
"hasPreviousPage": false,
"hasNextPage": true
}
}
手动实现物理分页
分页参数类
@Data
public class PageRequest {
private int pageNum = 1;
private int pageSize = 10;
public int getOffset() {
return (pageNum - 1) * pageSize;
}
}
Mapper XML(手动添加LIMIT)
<select id="selectPage" resultType="com.example.entity.User">
SELECT * FROM user
ORDER BY id DESC
LIMIT #{offset}, #{pageSize}
</select>
<select id="count" resultType="java.lang.Long">
SELECT COUNT(*) FROM user
</select>
Service 实现
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public Map<String, Object> getUserPage(PageRequest pageRequest) {
// 查询总数
long total = userMapper.count();
// 查询分页数据
List<User> list = userMapper.selectPage(
pageRequest.getOffset(),
pageRequest.getPageSize()
);
// 封装分页信息
Map<String, Object> result = new HashMap<>();
result.put("list", list);
result.put("total", total);
result.put("pageNum", pageRequest.getPageNum());
result.put("pageSize", pageRequest.getPageSize());
result.put("pages", (int) Math.ceil((double) total / pageRequest.getPageSize()));
return result;
}
}
使用 MyBatis-Plus 分页
配置
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
Service 实现
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public IPage<User> getUserPage(int current, int size) {
// 创建分页对象
Page<User> page = new Page<>(current, size);
// 方式一:无条件分页查询
return userMapper.selectPage(page, null);
// 方式二:带条件的分页查询
// QueryWrapper<User> wrapper = new QueryWrapper<>();
// wrapper.like("username", "张");
// return userMapper.selectPage(page, wrapper);
}
}
通用分页工具类
@Data
public class PageResult<T> {
private List<T> list;
private long total;
private int pageNum;
private int pageSize;
private int pages;
private boolean isFirstPage;
private boolean isLastPage;
public static <T> PageResult<T> of(List<T> list, long total, int pageNum, int pageSize) {
PageResult<T> result = new PageResult<>();
result.setList(list);
result.setTotal(total);
result.setPageNum(pageNum);
result.setPageSize(pageSize);
result.setPages((int) Math.ceil((double) total / pageSize));
result.setFirstPage(pageNum == 1);
result.setLastPage(pageNum >= result.getPages());
return result;
}
}
最佳实践建议
- 推荐使用 PageHelper:简单易用,自动拦截 SQL 添加分页
- 统一分页参数传递:使用 DTO 或 PageRequest 对象
- 合理设置默认值:pageNum=1, pageSize=10
- 限制最大分页大小:防止恶意查询
- 复杂查询建议使用 PageHelper:避免手动编写 LIMIT 和 COUNT
// 限制最大分页大小
@GetMapping("/page")
public Result<PageInfo<User>> getUserPage(
@RequestParam(defaultValue = "1") int pageNum,
@RequestParam(defaultValue = "10") int pageSize) {
// 限制最大分页大小
if (pageSize > 100) {
pageSize = 100;
}
PageInfo<User> pageInfo = userService.getUserByPage(pageNum, pageSize);
return Result.success(pageInfo);
}
这样,你就有了完整的 MyBatis 分页实现方案,推荐使用 PageHelper 插件版本,它是最简单且功能最完善的分页实现方式。