分页的场景比较常见,下面主要介绍一下使用PageHelper插件进行分页操作:
一、概述:
PageHelper支持对mybatis进行分页操作,项目在github地址:
https://github.com/pagehelper/Mybatis-PageHelper ;
项目中文官网:
https://pagehelper.github.io/
二、使用(与springboot集成):
springboot相比于spring,相关配置都可以在代码中完成,和之前通过xml配置的方式不同。
1. mybatis数据源配置中,对sqlSessionFactory bean对象配置的时候,声明定义PageHelper对象,对sessionFactory对象设置此分页对象插件:
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
// 分页插件
PageHelper pageHelper = new PageHelper();
Properties properties = new Properties();
properties.setProperty("reasonable", "true");
properties.setProperty("supportMethodsArguments", "true");
properties.setProperty("returnPageInfo", "check");
properties.setProperty("params", "count=countSql");
pageHelper.setProperties(properties);
// 添加插件
bean.setPlugins(new Interceptor[] { pageHelper });
如上代码,设置了分页插件的相关参数,相关参数的配置与效果可以进入插件官网查看。
2. 在需要分页的地方:
PageHelper.startPage(1, 10); List<Country> list = countryMapper.queryList(1);
如上,调用了PageHelper的startPage方法,传入第几页以及每页的记录数,这样就可以查询出对应的记录;
如果需要获取查询记录的总页数以及总记录数:
Page<?> page = PageHelper.startPage(1, 10); List<Country> list = countryMapper.queryList(1); int pages = page.getPages(); int total = (int)page.getTotal();
三、原理:
上面介绍了PageHelper插件分页功能的使用,总体来说还是比较方便的,不需要自己再去做额外的处理;
name为什么使用了如下语句之后,就可以生效呢?
PageHelper.startPage(1, 10); 简单的看下这个方法的源码,一直追踪下去,可以发现最终调用的是这个方法:
1 public static <E> Page<E> startPage(int pageNum, int pageSize, boolean count, Boolean reasonable, Boolean pageSizeZero) {
2 Page<E> page = new Page<E>(pageNum, pageSize, count);
3 page.setReasonable(reasonable);
4 page.setPageSizeZero(pageSizeZero);
5
6 Page<E> oldPage = SqlUtil.getLocalPage();
7 if (oldPage != null && oldPage.isOrderByOnly()) {
8 page.setOrderBy(oldPage.getOrderBy());
9 }
10 SqlUtil.setLocalPage(page);
11 return page;
12 }
可以看到,传入的pageNumber与pageSize最后是调用 SqlUtil.setLocalPage(page) 方法存了起来,我们看下这个方法:
public static void setLocalPage(Page page) {
LOCAL_PAGE.set(page);
}
那么这个LOCAL_PAGE对象是什么呢?
private static final ThreadLocal<Page> LOCAL_PAGE = new ThreadLocal<Page>();
其实就是一个threadlocal对象,用来存当前线程下pagenumber与pagesize;
那么可以推测,mybaits在执行查询的时候,由于设置了分页插件拦截器,会对查询sql进行处理,拼接对应页的查询语句,那么具体是哪一页以及每页有多少条记录,这些信息
就可以从这个threadlocal对象中取得。