SpringBoot 整合 MyBatis-Plus 分页插件完整教程
SpringBoot 整合 MyBatis-Plus 分页插件完整教程
一、前置说明
- MP 分页必须手动注册分页拦截器,不配置会出现分页 total 总条数为 0、不分页的问题;
- 适配 MP 3.5+ 新版写法(MybatisPlusInterceptor 统一插件入口),废弃旧版 PaginationInterceptor;
- 支持 MySQL、Oracle 等多种数据库,可指定数据库类型优化分页 SQL。
二、第一步:编写分页配置类
新建配置包com.config,创建MyBatisPlusConfig.java
java
运行
package com.config; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class MyBatisPlusConfig { /** * 注册MyBatis-Plus统一拦截器 */ @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); // 分页插件 PaginationInnerInterceptor pageInterceptor = new PaginationInnerInterceptor(); // 可选:设置数据库类型,自动适配分页语法,MySQL可不写 // pageInterceptor.setDbType(DbType.MYSQL); // 可选:设置单页最大条数,防止恶意超大分页查询 pageInterceptor.setMaxLimit(1000L); interceptor.addInnerInterceptor(pageInterceptor); return interceptor; } }参数说明
setMaxLimit(1000L):限制单次查询最多 1000 条,避免LIMIT 1,100000深度分页拖垮数据库;DbType.MYSQL:数据库类型,MP 自动生成分页语句,多数据源场景建议显式指定。
三、分页使用方式(Service 层标准用法)
1. 分页对象构造
Page<T>两个参数:当前页码、每页条数
java
运行
// 第1页,每页10条 Page<OrderInfo> page = new Page<>(1, 10);2. 配合 LambdaQueryWrapper 条件分页
java
运行
@Autowired private OrderInfoService orderInfoService; public Page<OrderInfo> getOrderPage(Integer pageNum, Integer pageSize) { // 1. 分页对象 Page<OrderInfo> page = new Page<>(pageNum, pageSize); // 2. 查询条件 LambdaQueryWrapper<OrderInfo> wrapper = new LambdaQueryWrapper<>(); wrapper.eq(OrderInfo::getIsDelete, 0) .orderByDesc(OrderInfo::getCreateTime); // 3. 执行分页查询 Page<OrderInfo> pageResult = orderInfoService.page(page, wrapper); return pageResult; }3. 返回分页对象常用属性
java
运行
// 当前页数据列表 List<OrderInfo> records = pageResult.getRecords(); // 总数据条数 long total = pageResult.getTotal(); // 总页数 long pages = pageResult.getPages(); // 当前页码 long current = pageResult.getCurrent(); // 每页条数 long size = pageResult.getSize();四、Mapper 层直接分页(不推荐,优先 Service)
java
运行
Page<OrderInfo> page = new Page<>(1,10); LambdaQueryWrapper<OrderInfo> wrapper = new LambdaQueryWrapper<>(); Page<OrderInfo> pageResult = orderInfoMapper.selectPage(page, wrapper);五、自定义 XML 多表联查分页(原生 SQL 分页兼容)
1. Mapper 接口
java
运行
Page<OrderVO> selectOrderPage(Page<OrderVO> page, @Param("name") String name);2. XML 不需要手写 LIMIT,MP 自动拼接分页语句
xml
<select id="selectOrderPage" resultType="com.vo.OrderVO"> SELECT o.*, p.product_name FROM order_info o LEFT JOIN product p ON o.product_id = p.id <where> <if test="name != null and name != ''"> p.product_name LIKE CONCAT('%',#{name},'%') </if> o.is_delete = 0 </where> ORDER BY o.create_time DESC </select>六、常见问题与解决方案
问题 1:分页查询 total 总条数为 0
原因:未配置MybatisPlusInterceptor分页插件; 解决:复制上方配置类,确保被 Spring 扫描到(加@Configuration)。
问题 2:深度分页 LIMIT 100000,10 很慢
优化:
- 配置
setMaxLimit限制最大单页条数; - 大分页使用主键偏移分页替代普通分页。
问题 3:XML 自定义 SQL 分页失效
- 方法第一个参数必须是
Page<T>; - 不要自己手写
limit,会重复拼接导致语法报错。
问题 4:分页插件与乐观锁 / 防全表更新插件共存
直接叠加添加内部拦截器即可:
java
运行
interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());七、Controller 接收分页参数标准示例
java
运行
@GetMapping("/order/page") public Result<Page<OrderInfo>> orderPage( @RequestParam(defaultValue = "1") Integer pageNum, @RequestParam(defaultValue = "10") Integer pageSize ) { Page<OrderInfo> pageData = orderInfoService.getOrderPage(pageNum, pageSize); return Result.success(pageData); }