游乐游手机版
首页/编程语言/文章详情

MyBatis-Plus实现分页查询两种方案详解

时间:2026-05-05 12:08
方案一:PageUtils 工具类分页(ThreadLocal 封装版) 1 方案概述 在不少传统或存量项目中,你可能会遇到一个熟悉的“老朋友”:PageUtils startPage()。这通常是项目内部统一封装的分页工具类,其底层基于 MyBatis-Plus 的分页插件。它的最大魅力在于,通

方案一:PageUtils 工具类分页(ThreadLocal 封装版)

1. 方案概述

在不少传统或存量项目中,你可能会遇到一个熟悉的“老朋友”:PageUtils.startPage()。这通常是项目内部统一封装的分页工具类,其底层基于 MyBatis-Plus 的分页插件。它的最大魅力在于,通过 ThreadLocal 技术存储分页参数,实现了对业务代码的“零侵入”。对于不希望动刀原有逻辑的场景,它往往是首选。

MyBatis-Plus实现分页查询两种方案详解

2. 核心原理

  1. 当你在 Controller 层调用 startPage() 时,工具类会悄无声息地获取前端传来的页码和每页条数
  2. 随后,MyBatis-Plus 的分页拦截器会精准拦截后续的 SQL 执行,并自动拼接上 LIMIT 语句;
  3. 最终,查询返回的普通 List 集合,会被工具类自动“包装”成一个标准的分页结果集,返回给前端。

整个过程,Service 和 Mapper 层完全感知不到分页的存在,仿佛什么都没发生。

3. 适用场景

  • 项目已经存在一变钱成的、封装好的分页工具类。
  • 核心诉求是不改动原有的 Mapper 或 Service 层代码。
  • 追求快速实现分页功能,进行低成本的系统改造。

4. 完整代码示例

4.1 Controller 层

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import ja vax.annotation.Resource;
import ja va.util.List;

/**
 * 案件维度管理 Controller
 */
@RestController
@RequestMapping("/justice/case/dimension")
public class JusticeCaseDimensionController {

    @Resource
    private CaseDimensionContext caseDimensionContext;

    /**
     * 按范围查询案件聚合维度(账龄+批次号/被告)
     * 方案一:PageUtils 工具类分页
     */
    @GetMapping("/selectCaseDimensionByScope")
    public R selectCaseDimensionByScope(JusticeCaseDimensionQuery caseDimensionQuery) {
        // 1. 开启分页(核心:自动接收前端 page/pageSize 参数)
        PageUtils.startPage();
        
        // 2. 执行业务查询,返回普通 List 集合
        List justiceCaseDimensions = caseDimensionContext.selectCaseDimensionByScope(caseDimensionQuery);
        
        // 3. 工具类封装 List 为分页结果返回
        return R.page(justiceCaseDimensions);
    }
}

4.2 Service/Mapper 层

这里无需任何分页相关代码,保持原样,正常返回 List 集合即可。这正是该方案“无侵入性”的体现。

二、方案二:MyBatis-Plus 原生 IPage 分页(官方推荐)

1. 方案概述

如果说方案一是“民间智慧”,那么 IPage(或其实现类 Page)就是 MyBatis-Plus 框架官方钦定的分页对象。它通过方法参数和返回值来显式传递分页信息,代码意图清晰,结构规范,是新项目启动时的标准答案。

2. 核心原理

  1. 前端传递的 page、pageSize 参数,会被 SpringMVC 自动绑定并封装成一个 Page 对象;
  2. 将这个 Page 对象作为参数传入查询方法,MyBatis-Plus 便会心领神会地进行分页查询;
  3. 方法直接返回 IPage 对象,其中总条数、总页数、当前页数据等分页要素一应俱全,无需二次封装。

3. 适用场景

  • 全新项目的开发,希望遵循官方最佳实践。
  • 需要清晰、明确的分页参数传递路径,便于代码阅读和维护。
  • 追求极简的代码结构,降低长期的维护成本。

4. 完整代码示例

4.1 Controller 层(业务接口)

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import ja vax.annotation.Resource;

/**
 * 案件维度管理 Controller
 */
@RestController
@RequestMapping("/justice/case/dimension")
public class JusticeCaseDimensionController {

    @Resource
    private CaseDimensionContext caseDimensionContext;

    /**
     * 按范围查询案件聚合维度(账龄+批次号/被告)
     * 方案二:原生 IPage 分页(官方推荐)
     */
    @GetMapping("/selectCaseDimensionByScope")
    public R> selectCaseDimensionByScope(
            // 分页参数:自动接收 page、pageSize
            Page page,
            JusticeCaseDimensionQuery caseDimensionQuery
    ) {
        // 1. 直接传入 Page 对象,返回 IPage 分页结果
        IPage pageResult = caseDimensionContext.selectCaseDimensionByScope(page, caseDimensionQuery);
        
        // 2. 直接返回原生分页对象
        return R.ok(pageResult);
    }
}

4.2 Service 层

/**
 * Service 层方法
 */
public IPage selectCaseDimensionByScope(Page page, JusticeCaseDimensionQuery query) {
    // 调用 Mapper,直接返回 IPage
    return baseMapper.selectCaseDimensionByScope(page, query);
}

4.3 Mapper 层

/**
 * Mapper 层方法
 */
IPage selectCaseDimensionByScope(Page page, @Param("query") JusticeCaseDimensionQuery query);

三、两种分页方案核心对比

对比维度 PageUtils 工具类分页 原生 IPage 分页
官方推荐度 非官方,项目自定义封装 ✅ MyBatis-Plus 官方标准
代码侵入性 无侵入,无需修改原有接口 轻度侵入,需传入 Page 对象
代码简洁度 需手动开启分页 + 封装结果 一步到位,代码极简
分页信息 工具类自动封装 自带完整分页信息(总条数 / 总页数)
适用项目 老项目、存量系统改造 新项目、标准化开发
学习成本 低(直接调用工具方法) 低(原生对象,无额外学习)

四、最佳实践建议

  1. 新项目优先使用原生 IPage 分页:这是框架的“亲儿子”,符合官方规范,代码结构清晰,长期维护和团队协作成本更低。
  2. 老项目保留 PageUtils 分页:对于存量系统,这种无侵入式的方案能最大程度保持代码稳定,避免牵一发而动全身的改造风险。
  3. 统一项目规范是关键:无论选择哪种,在一个项目内部务必保持统一。混合使用两种风格,只会让代码库变得难以理解和维护。
来源:https://www.jb51.net/program/362328ttu.htm
上一篇c#如何判断字典是否包含某个key_c#判断字典是否包含某个key深入理解与底层原理 下一篇如何使用cursor实现安装windows工具
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
PyTorch中使用多维索引张量对高维张量批量索引的正确方法
编程语言 · 2026-07-03

PyTorch中使用多维索引张量对高维张量批量索引的正确方法

本文深入讲解如何在 PyTorch 中利用形状为 [b, k] 的索引张量 B,对形状为 [b, m, n] 的高维张量 A 执行高效批量索引,最终得到 [b, k, n] 的输出。核心思路在于合理扩展索引维度并配合 torch gather 实现精准的逐行抽取。 很多人处理高维张量的批量索引时都会

Go中...操作符解包切片传递可变参数函数
编程语言 · 2026-07-03

Go中...操作符解包切片传递可变参数函数

在 Go 语言中,` ` 运算符放在切片变量后面(如 `slice `)的作用是将该切片“展开”为多个独立参数,专门用于调用那些接受可变参数(` T`)的函数,例如 `append` 或 `fmt Println`。这是一种类型安全的语法糖,并非省略号或通配符,能够帮助开发者更简洁地处理

macOS与WSL2下PHP多版本切换失效问题排查与修复指南
编程语言 · 2026-07-03

macOS与WSL2下PHP多版本切换失效问题排查与修复指南

本文深入分析在 macOS 或 WSL2(Ubuntu)开发环境中,通过 Homebrew 管理 PHP 多版本时,php -v 始终显示旧版本(如 php@5 6)的深层原因,并给出系统性解决方案,覆盖 PATH 冲突、符号链接逻辑、Shell 初始化配置、系统残留配置等关键环节。 遇到这种情况的

PHP JSON解析深层嵌套对象属性访问失败的解决方法
编程语言 · 2026-07-03

PHP JSON解析深层嵌套对象属性访问失败的解决方法

使用 json_decode() 解析 API 返回的 JSON 数据时,经常遇到某个子属性无法正常获取,始终返回 NULL —— 这是许多 PHP 开发者都曾碰到过的棘手问题。通常并非数据丢失,而是对象嵌套层级比预期更深,导致访问路径不正确。 举例来说,你看到返回的 JSON 里有一个 appea

nnU-Net v2预处理卡死问题的成因分析与实用解决指南
编程语言 · 2026-07-03

nnU-Net v2预处理卡死问题的成因分析与实用解决指南

> 使用 nnUNetv2_plan_and_preprocess 处理大规模数据集(例如 704 例样本)时,程序常因多进程加载导致死锁而停滞。核心原因在于默认并发数过高引发资源竞争或 I O 阻塞,适当降低并发数即可稳定完成全量预处理。 你在使用 `nnunetv2_plan_and_prepr