MyBatis实现分页全过程

 更新时间:2025年08月27日 08:44:49   作者: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语句(像有个智能机器人帮你从书架上拿指定范围的书)。

配置步骤

  1. 添加依赖:
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>5.3.2</version>
</dependency>
  1. 配置拦截器(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

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Java 集合系列(二)ArrayList详解

    Java 集合系列(二)ArrayList详解

    这篇文章主要介绍了Java集合系列ArrayList,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-03-03
  • Java匿名内部类导致内存泄露的原因与解决方案详解

    Java匿名内部类导致内存泄露的原因与解决方案详解

    这篇文章主要为大家详细介绍了Java因为匿名内部类导致内存泄露的原因以及其解决方案,文中的示例代码讲解详细,希望对大家有所帮助
    2022-11-11
  • springboot排除某些自动配置的操作方法

    springboot排除某些自动配置的操作方法

    Spring Boot 提供的自动配置非常强大,某些情况下,自动配置的功能可能不符合我们的需求,需要我们自定义配置,这个时候就需要排除/禁用Spring Boot 某些类的自动化配置了,本文给大家介绍springboot排除某些自动配置的方法,感兴趣的朋友一起看看吧
    2023-08-08
  • Java模拟实现HTTP服务器项目实战

    Java模拟实现HTTP服务器项目实战

    本文主要介绍了Java模拟实现HTTP服务器项目实战,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • Java 动态生成类和实例, 并注入方法操作示例

    Java 动态生成类和实例, 并注入方法操作示例

    这篇文章主要介绍了Java 动态生成类和实例, 并注入方法操作,结合实例形式分析了Java 动态生成类和实例以及动态注入相关操作技巧,需要的朋友可以参考下
    2020-02-02
  • Java代理模式与动态代理之间的关系以及概念

    Java代理模式与动态代理之间的关系以及概念

    代理模式是开发中常见的一种设计模式,使用代理模式可以很好的对程序进行横向扩展。动态代理:代理类在程序运行时被创建的代理方式。关键在于动态,程序具有了动态特性,可以在运行期间根据不同的目标对象生成动态代理对象
    2023-02-02
  • Java内部类的实现原理与可能的内存泄漏说明

    Java内部类的实现原理与可能的内存泄漏说明

    这篇文章主要介绍了Java内部类的实现原理与可能的内存泄漏说明,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-10-10
  • 带你粗略了解Java数组的使用

    带你粗略了解Java数组的使用

    这篇文章主要给大家介绍了关于Java中数组的定义和使用的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-08-08
  • Spring IOC:CreateBean环节中的流程转换

    Spring IOC:CreateBean环节中的流程转换

    Spring IOC 体系是一个很值得深入和研究的结构 , 只有自己真正的读一遍 , 才能有更好的理解.这篇文章主要说明一下 CreateBean 整个环节中的大流程转换 , 便于查找问题的原因
    2021-05-05
  • java 排序算法之快速排序

    java 排序算法之快速排序

    这篇文章主要介绍了java 排序算法之快速排序,文中通过图片和代码讲解相关知识非常详细,大家如果有需要的话可以参考一下这篇文章
    2021-09-09

最新评论