分页是基于WEB的应用绕不开的话题,一般情况下基于Mybatis的java项目可选的分页方案包括:
- 开源项目PageHelper。
- 基于Mybatis的RowBounds分页。
- Mybatis-plus分页。
- 自己实现的分页方案。
今天我们主要分析前两种分页方案,Mybatis-plus的分页放在下一篇文章中分析。除非有特殊原因,一般情况下也不太建议自己再去实现分页方案,因为无论是PageHelper还是Mybatis-plus的分页方案,绝大部分情况下也够用了,没有必要重复造轮子。
物理分页和逻辑分页
一般来讲,分页针对的是执行数据库查询的时候,符合条件的数据有很多、但是前端页面一次不需要展示全部数据的应用场景。
在这一场景下,应用层获取当前页数据的方案自然就分为两种:一种是应用层向数据库获取所有满足条件的数据,然后在应用层内存中对结果集进行过滤、获取到当前页数据后返回给前端。另一种需要数据库的支持,应用层只向数据库请求当前页的数据、获取数据后直接返回给前端。
第一种方式就是我们常说的逻辑分页,也可以叫内存分页。第二种方式就是物理分页。
两种方式的区别其实一目了然,逻辑分页不止是对数据库有内存、性能的压力,而且对于网络传输、应用层内存都会存在性能压力。尤其是在满足条件的数据量特别大(比如10w条)、而当前页需要的数据量比较小(一般情况下都会比较小,比如10条)的情况下,应用层获取到的绝大部分数据都被丢弃了,所以对于数据库服务器内存、网络、应用服务器内存都是一种极大地浪费。
而物理分页由于从数据库获取到的数据量比较小,所以性能压力比较小。
因此,正式项目即使前期能够判断将来数据量不会太大的情况下,也不建议使用逻辑分页方案。
当然,物理分页需要数据库的支持,比如MySQL的limit,Oracle的rownum等等,目前大部分的主流数据库都可以提供类似的支持。
基于Mybatis的RowBounds的分页实现
Mybatis内置提供了基于RowBounds的分页方案,只要我们在mapper接口中提供RowBounds参数,Mybatis自然就可以帮我们实现分页。
但是我们必须要知道,RowBounds是逻辑分页!所以我们用学习了解的态度来研究一下RowBounds分页方案的实现机制,项目中不建议直接使用。
基于RowBounds的分页实现非常简单,只要在mapper接口中设置RowBounds参数即可,比如获取所有用户的接口:
List<User> selectPagedAllUsers(RowBounds rowBounds);
List<User> selectAllUsers();
在mapper.xml文件中上述两个接口对应的sql语句可以完全一样,selectPagedAllUsers是实现分页的接口,selectAllUsers是不分页的接口。
那么我们应该怎么传递RowBounds呢?首先要了解一下RowBounds具体是个什么东东。
其实RowBounds的定义很简单,最重要的两个参数,offset其实就是起始位置,limit可以理解为每页行数。
private final int offset;
private final int limit;
public RowBounds(int offset, int limit) {
this.offset = offset;