如果你也在用Mybatis,建议尝试该分页插件,这一定是最方便使用的分页插件。
分页插件支持任何复杂的单表、多表分页,部分特殊情况请看。
想要使用分页插件?请看。
物理分页
该插件目前支持以下数据库的物理分页:
Oracle
Mysql
MariaDB
SQLite
Hsqldb
PostgreSQL
DB2
SqlServer(2005,2008)
Informix
H2
SqlServer2012
配置dialect
属性时,可以使用小写形式:
oracle
,mysql
,mariadb
,sqlite
,hsqldb
,postgresql
,db2
,sqlserver
,informix
,h2
,sqlserver2012
在4.0.0版本以后,dialect
参数可以不配置,系统能自动识别这里提到的所有数据库。
对于不支持的数据库,可以实现com.github.pagehelper.parser.Parser
接口,然后配置到dialect
参数中(4.0.2版本增加)。
特别注意:使用SqlServer2012数据库时,需要手动指定sqlserver2012
,否则会使用2005的方式进行分页。
MyBatis工具网站:
分页插件支持MyBatis3.2.0~3.3.0(包含)
分页插件最新版本为4.1.6
Maven坐标
dependency> com.github.pagehelper pagehelper 4.1.6
下载JAR包
分页插件pagehelper.jar:
由于使用了sql解析工具,你还需要下载jsqlparser.jar
使用方法
1. 引入分页插件
引入分页插件一共有下面2种方式,推荐使用Maven方式,这种方式方便更新。
1). 引入Jar包
如果你想使用本项目的jar包而不是直接引入类,你可以在这里下载各个版本的jar包(点击Download下的jar即可下载)
由于使用了sql解析工具,你还需要下载jsqlparser.jar(这个文件完全独立,不依赖其他):
2). 使用maven
添加如下依赖:
com.github.pagehelper pagehelper 4.1.6
当使用maven中央库中的快照版(带"-SNAPSHOT"
的版本)时,需要在pom.xml中添加如下配置:
sonatype-nexus-snapshots Sonatype Nexus Snapshots http://oss.sonatype.org/content/repositories/snapshots false true
2. 在Mybatis配置xml中配置拦截器插件:
这里的com.github.pagehelper.PageHelper
使用完整的类路径。
其他五个参数说明:
-
增加
dialect
属性,使用时可以指定该属性(不指定的情况下,分页插件会自动判断),可选值为oracle
,mysql
,mariadb
,sqlite
,hsqldb
,postgresql
,db2
,sqlserver
,informix
,h2
,sqlserver2012
。 -
增加
offsetAsPageNum
属性,默认值为false
,使用默认值时不需要增加该配置,需要设为true
时,需要配置该参数。当该参数设置为true
时,使用RowBounds
分页时,会将offset
参数当成pageNum
使用,可以用页码和页面大小两个参数进行分页。 -
增加
rowBoundsWithCount
属性,默认值为false
,使用默认值时不需要增加该配置,需要设为true
时,需要配置该参数。当该参数设置为true
时,使用RowBounds
分页会进行count查询。 -
增加
pageSizeZero
属性,默认值为false
,使用默认值时不需要增加该配置,需要设为true
时,需要配置该参数。当该参数设置为true
时,如果pageSize=0
或者RowBounds.limit = 0
就会查询出全部的结果(相当于没有执行分页查询,但是返回结果仍然是Page
类型)。 -
增加
reasonable
属性,默认值为false
,使用默认值时不需要增加该配置,需要设为true
时,需要配置该参数。具体作用请看上面配置文件中的注释内容。 -
为了支持
startPage(Object params)
方法,增加了一个params
参数来配置参数映射,用于从Map或ServletRequest中取值,可以配置pageNum,pageSize,count,pageSizeZero,reasonable,orderBy,不配置映射的用默认值。 -
supportMethodsArguments
支持通过Mapper接口参数来传递分页参数,默认值false
,具体用法参考com.github.pagehelper.test.basic
包下的ArgumentsMapTest
和ArgumentsObjTest
测试类。 -
returnPageInfo
用来支持直接返回PageInfo
类型,默认值none
,可选参数always总是返回PageInfo类型,check检查返回类型是否为PageInfo,none返回Page(List)类型。用法和配置参考com.github.pagehelper.test.basic
包下的PageInfoTest
,特别要注意接口的返回值和xml中的resultType
类型。 -
增加
closeConn
属性,当使用动态数据源或没有设置dialect
属性自动获取数据库类型时,会自动获取一个数据库连接,通过该属性来设置是否关闭获取的这个连接,默认true
关闭。
重要提示:
当offsetAsPageNum=false
的时候,由于PageNum问题,RowBounds
查询的时候reasonable会强制为false。使用PageHelper.startPage
方法不受影响。
另外使用RowBounds
在这种情况下返回的Page
对象由于没有正确的pageNum
属性,所以也不能使用PageInfo
处理。
如果你不理解为什么,可以看这样一个例子:查询offset=7,limit=10
,这个时候pageNum=?
,这种情况没法计算pageNum
,没法判断当前是第几页。
3. 如何选择配置这些参数
单独看每个参数的说明可能是一件让人不爽的事情,这里列举一些可能会用到某些参数的情况。
首先dialect
属性是必须的,不需要解释。其他的参数一般情况下我们都不必去管,如果想了解何时使用合适,你可以参考以下场景:
场景一
如果你仍然在用类似ibatis式的命名空间调用方式,你也许会用到rowBoundsWithCount
,分页插件对RowBounds
支持和Mybatis默认的方式是一致,默认情况下不会进行count查询,如果你想在分页查询时进行count查询,以及使用更强大的PageInfo
类,你需要设置该参数为true
。
场景二
如果你仍然在用类似ibatis式的命名空间调用方式,你觉得RowBounds中的两个参数offset,limit
不如pageNum,pageSize
容易理解,你可以使用offsetAsPageNum
参数,将该参数设置为true
后,offset
会当成pageNum
使用,limit
和pageSize
含义相同。
场景三
如果觉得某个地方使用分页后,你仍然想通过控制参数查询全部的结果,你可以配置pageSizeZero
为true
,配置后,如可以通过设置pageSize=0
或者RowBounds.limit = 0
就会查询出全部的结果。
场景四
如果你分页插件使用于类似分页查看列表式的数据,如新闻列表,软件列表,你希望用户输入的页数不在合法范围(第一页到最后一页之外)时能够正确的响应到正确的结果页面,那么你可以配置reasonable
为true
,这时如果pageNum<1
会查询第一页,如果pageNum>总页数
会查询最后一页。
4. Spring配置方法
首先需要在Spring中配置org.mybatis.spring.SqlSessionFactoryBean
。然后配置配置Mybatis的具体配置有两种方式,一种是用mybatis默认的xml配置,另一种就是完全使用spring的属性配置方式。
1.mybatis默认的xml配置
配置configLocation
属性指向上面的mybatis-config.xml
文件。有关分页插件的配置都在mybatis-config.xml
,具体配置内容参考上面的mybatis-config.xml
。
2.使用spring的属性配置方式
注意:请不用同时使用spring配置方式和mybatis-config.xml配置方式,只需要选择其中一个就行。配置多个分页插件时,会抛出异常提示。
分页插件配置错误:请不要在系统中配置多个分页插件(使用Spring时,mybatis-config.xml和Spring配置方式,请选择其中一种,不要同时配置多个分页插件)!
使用spring的属性配置方式,可以使用plugins
属性像下面这样配置:
classpath:mapper/*.xml dialect=hsqldb
属性配置按照上面的方式配置,每个配置独立一行即可。
5. 如何在代码中使用
阅读前后请注意看
首先该分页插件支持以下两种调用方式:
//第一种,RowBounds方式的调用List list = sqlSession.selectList("x.y.selectIf", null, new RowBounds(1, 10));//第二种,Mapper接口方式的调用,推荐这种使用方式。PageHelper.startPage(1, 10);List list = countryMapper.selectIf(1);
下面分别对这两种方式进行详细介绍
1). RowBounds方式的调用
List list = sqlSession.selectList("x.y.selectIf", null, new RowBounds(1, 10));
使用这种调用方式时,你可以使用RowBounds参数进行分页,这种方式侵入性最小,我们可以看到,通过RowBounds方式调用只是使用了这个参数,并没有增加其他任何内容。
分页插件检测到使用了RowBounds参数时,就会对该查询进行物理分页。
关于这种方式的调用,有两个特殊的参数是针对RowBounds
的,你可以参看上面的和
注:不只有命名空间方式可以用RowBounds,使用接口的时候也可以增加RowBounds参数,例如:
//这种情况下也会进行物理分页查询List selectAll(RowBounds rowBounds);
2). PageHelper.startPage
静态方法调用
在你需要进行分页的Mybatis方法前调用PageHelper.startPage
静态方法即可,紧跟在这个方法后的第一个Mybatis查询方法会被进行分页。
例一:
SqlSession sqlSession = MybatisHelper.getSqlSession();CountryMapper countryMapper = sqlSession.getMapper(CountryMapper.class);try { //获取第1页,10条内容,默认查询总数count PageHelper.startPage(1, 10); //紧跟着的第一个select方法会被分页 List list = countryMapper.selectIf(1); assertEquals(2, list.get(0).getId()); assertEquals(10, list.size()); //分页时,实际返回的结果list类型是Page ,如果想取出分页信息,需要强制转换为Page , //或者使用PageInfo类(下面的例子有介绍) assertEquals(182, ((Page) list).getTotal());} finally { sqlSession.close();}
例二:
SqlSession sqlSession = MybatisHelper.getSqlSession();CountryMapper countryMapper = sqlSession.getMapper(CountryMapper.class);try { //获取第1页,10条内容,默认查询总数count PageHelper.startPage(1, 10); //紧跟着的第一个select方法会被分页 List list = countryMapper.selectIf(1); //后面的不会被分页,除非再次调用PageHelper.startPage List list2 = countryMapper.selectIf(null); //list1 assertEquals(2, list.get(0).getId()); assertEquals(10, list.size()); //分页时,实际返回的结果list类型是Page ,如果想取出分页信息,需要强制转换为Page , //或者使用PageInfo类(下面的例子有介绍) assertEquals(182, ((Page) list).getTotal()); //list2 assertEquals(1, list2.get(0).getId()); assertEquals(182, list2.size());} finally { sqlSession.close();}
例三,使用PageInfo
的用法:
//获取第1页,10条内容,默认查询总数countPageHelper.startPage(1, 10);List list = countryMapper.selectAll();//用PageInfo对结果进行包装PageInfo page = new PageInfo(list);//测试PageInfo全部属性//PageInfo包含了非常全面的分页属性assertEquals(1, page.getPageNum());assertEquals(10, page.getPageSize());assertEquals(1, page.getStartRow());assertEquals(10, page.getEndRow());assertEquals(183, page.getTotal());assertEquals(19, page.getPages());assertEquals(1, page.getFirstPage());assertEquals(8, page.getLastPage());assertEquals(true, page.isFirstPage());assertEquals(false, page.isLastPage());assertEquals(false, page.isHasPreviousPage());assertEquals(true, page.isHasNextPage());
本项目中包含大量测试,您可以通过查看测试代码了解使用方法。
测试代码地址:
MyBatis和Spring集成示例
如果和Spring集成不熟悉,可以参考下面两个
只有基础的配置信息,没有任何现成的功能,作为新手入门搭建框架的基础
这两个集成框架集成了MyBatis分页插件和MyBatis通用Mapper。