优秀的编程知识分享平台

网站首页 > 技术文章 正文

MyBatis中的翻页

nanyue 2024-11-21 18:56:18 技术文章 2 ℃

在我们的查询数据库的操作中,有两种分页方式,一种是逻辑翻页(假翻页), 一种是物理翻页(真分页)。


逻辑分页的原理就是把所有数据都查询出来,在内存中筛选数据。物理分页是真正的分页,比如MySQL使用Limit语句,Oracle使用rownum语句,SQL Server使用top语句。


逻辑翻页

MyBatis中有一个逻辑翻页对象RowBounds,里面主要有两个属性,offset和limit(从第几条开始,查询多少数据)。


我们可以在mapper接口方法上加上这个参数,不需要修改xml里面SQL语句。

public List<Blog> selectBlogList(RowBounds rowBounds);

使用:

int start = 10;
int pageSize = 5;
RowBounds rb = new RowBounds(start, pageSize);
List<Blog> list = mapper.selectBlogList(rb);
for (Blog blog : list) {
  System.out.println(blog);
}

它的底层是对ResultSet的处理,它会舍弃掉前面offset条数据,然后再取剩下数据的limit条。

private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping)
      throws SQLException {
    DefaultResultContext<Object> resultContext = new DefaultResultContext<Object>();
    skipRows(rsw.getResultSet(), rowBounds);
    while (shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) {
      ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(rsw.getResultSet(), resultMap, null);
      Object rowValue = getRowValue(rsw, discriminatedResultMap);
      storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());
    }
  }

很明显,如果数据量大的话,这种分页效率会很低(和查询到内存中再使用subList(start, end)没有什么区别),所以我们一般会使用物理分页。

物理分页

物理分页是真实的分页,它是通过数据库支持的语句来实现分页功能的。

第一种简单的办法就是传入参数(或者包装成一个page对象), 在SQL语句中分页。

<select id="selectBlogPage" parameterType="map" resultType="baseMap">
  select * from tb_blog limit #{curIndex}, #{pageSize}
</select>

这种方法有一个问题就是我们要在Java代码中计算起止序号,第二个问题就是每一个需要分页的statement都要编写limit语句,会造成Mapper映射器中有很多冗余代码。


那我们就需要一种通用的方式,不需要去修改配置的任何一条SQL语句,只要在我们需要分页的地方封装一下分页对象就可以了。

最常用的做法是使用分页插件,这个是基于MyBatis的拦截器实现的,比如PageHelper。

PageHelper.startPage(pn, 10);
List<Employee> list = mapper.getAll();
PageInfo page = new PageInfo(list, 10);
return Msg.success().add("pageInfo", page);

PageHelper是根据MyBatis的拦截器实现的,简单的说,它会根据PageHelper的参数,改写我们的SQL,比如MySQL会生成limit,Oracle会生成rownum。

Tags:

最近发表
标签列表