mybatis 分页插件原理是什么样的?

@RequestMapping(value = "/findAll",method = RequestMethod.GET)
    public String  getUsers(){
        int pageNum = 1;
        int pageSize = 10;
        PageHelper.startPage(pageNum, pageSize);
        List<User> list = userService.findAllUser();
        PageInfo pageInfo = new PageInfo(list);
        Page page = (Page) list;
        return "PageInfo: " + JSON.toJSONString(pageInfo) + ", Page: " + JSON.toJSONString(page);
    }
<select id="findAllUser" resultType="User">
        SELECT * from users
    </select>
PageInfo: {"endRow":10,"firstPage":1,"hasNextPage":true,"hasPreviousPage":false,"isFirstPage":true,"isLastPage":false,"lastPage":2,"list":[{"id":2,"name":"awbeci"},{"id":3,"name":"wulingmei"},{"id":4,"name":"qinxin"},{"id":5,"name":"qinxin2"},{"id":6,"name":"qinxin3"},{"id":7,"name":"???"},{"id":8,"name":"caochenglu"},{"id":10,"name":"sdfsdfs"},{"id":13,"name":"wangle"},{"id":14,"name":"react-cd-player"}],"navigateFirstPage":1,"navigateLastPage":2,"navigatePages":8,"navigatepageNums":[1,2],"nextPage":2,"pageNum":1,"pageSize":10,"pages":2,"prePage":0,"size":10,"startRow":1,"total":17}, Page: [{"id":2,"name":"awbeci"},{"id":3,"name":"wulingmei"},{"id":4,"name":"qinxin"},{"id":5,"name":"qinxin2"},{"id":6,"name":"qinxin3"},{"id":7,"name":"???"},{"id":8,"name":"caochenglu"},{"id":10,"name":"sdfsdfs"},{"id":13,"name":"wangle"},{"id":14,"name":"react-cd-player"}]

根据上面代码,确实可以分页了,但是我有点想不通:因为我的查询语句是select * from users,难道是我先从数据库中查询出所有数据,然后再在getUsers方法里面通过查询插件再进行分页???

阅读 6k
3 个回答

你代码使用了mybatis page helper插件,他本身是一个物理分页插件,实际原理就是修改最后的执行sql,增加xi相应的分页内容,是基于拦截器实现的。

例如,首先你配置了PageHelper的page number和size,调用完startPage后,他会通过PageInterceptor对其后的第一个执行sql进行拦截,也就是对List<User> list = userService.findAllUser()进行拦截,这里原本的sql可能是 select * from users,他会自动拼接上分页的sql语句,比如mysql环境的话,就是拼接上limit语句,随后执行,最后的结果,可以通过PageInfo和Page进行获取。

更详细的使用方法,你可以看他的文档 https://pagehelper.github.io/...,本身原理比较简单,你可以通过输出log或者debug步进的形式,来看一下最后执行的sql,实际也可以通过自己写个拦截器,做到同样的效果。

补充一下:mybatis原生也是支持分页的,但为了与数据库语法解耦,实现的是逻辑分页,首先将所有结果查询出来,然后通过计算offset和limit,只返回部分结果,操作在内存中进行,所以也叫内存分页,当数据量比较大的时候,肯定是不行的,核心类叫rowbounds,有兴趣可以搜一下。

看这个写法应该就是内存中分页了

查出一万条数据 再去数组中取中间10条 这是不可能的...

猜想是AOP. 打印出SQL 会发现每次都在SQL语句最后面加上了limit 0,10

如果写的SQL是
select *
from a , (select * from b ) c
这种格式,想要在 b中加limit 这插件就不行了

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题