什么是分页(pagination)
例如在数据库的某个表里有1000条数据,我们每次只显示100条数据,在第1页显示第0到第99条,在第2页显示第100到199条,依次类推,这就是分页。
分页可以分为逻辑分页和物理分页。
逻辑分页是我们的程序在显示每页的数据时,首先查询得到表中的1000条数据,然后成熟根据当前页的“页码”选出其中的100条数据来显示。不推荐使用。
物理分页是程序先判断出该选出这1000条的第几条到第几条,然后数据库根据程序给出的信息查询出程序需要的100条返回给我们的程序。
我们以 数据准备 的 blog 表为例学习如何使用mybatis进行分页查询。
blog 表数据如下:
项目结构:
log4j.properties 中配置让 mybatis 输出执行信息。
示例1:在 sql 中显式使用 limit
在 BlogMapper 接口中增加方法:
该方法作用是查询某个用户按照id升序排序的所有文章中,第limit篇开始的共offset篇博客。注意, limit 从 0 开始。
BlogMapper.xml 中的SQL 映射:
这个属于物理查询。
在 Main 类中编写示例代码:
执行 test_01 函数,结果为:
中间可以看到 mybatis 的执行语句和参数。最后两行是得到的查询结果。
示例2:使用 RowBounds 进行逻辑分页查询
mybatis 自带一个 RowBounds 类可以实现逻辑分页。
在 BlogMapper 接口中定义方法:
该方法作用是查询某个用户按照id升序排序的所有文章中,第rowBounds.getLimit()篇开始的共rowBounds.getOffset()篇博客。注意, limit 从 0 开始。mybatis 会自动识别出 RowBounds 参数。
BlogMapper.xml 中对应的 SQL 不必写 limit:
在 Main 类中编写示例代码:
执行结果:
可以看到执行的 SQL 并为使用 limit ,但获取的数据只有2条。这是因为mybatis把所有符合条件的数据都取出来了,然后根据 RowBounds 对象的内容取出部分数据返回。这种逻辑分页很明显是有问题的,比如有10000000条数据满足条件,这么大的数据量全部从mysql取出来耗时很长,从mysql传到java程序耗时很长,java程序的内存占用也会变很高,所以不推荐这种实现。
但这种写法很方便,我们有保持这种写法,而分页查询是物理分页的方案吗?有,用mybatis的拦截器(理解为插件,可以获取要执行的sql,修改sql)。已经有人做出这样的拦截器了,我们直接拿来用。
示例3:使用 RowBounds + PageHelper 进行物理分页查询
PageHelper(https://github.com/pagehelper/Mybatis-PageHelper) 是一个Mybatis分页插件,特性很丰富。
在 build.gradle 中引入依赖:
新建一个 mybatis-config-with-pagehelper.xml ,内容和mybatis-config.xml 基本一样,但引入了 pagehelper 插件:
在 Main 类中编写示例代码:
test_03 执行结果:
可以看到执行的SQL语句中出现了 LIMIT 。LIMIT 0, 2 与 LIMIT 2含义是一样的。