前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Mybatis分页插件PageHelper详解

Mybatis分页插件PageHelper详解

作者头像
用户5224393
发布2019-08-13 15:42:25
1.5K0
发布2019-08-13 15:42:25
举报
文章被收录于专栏:Java研发军团

作者:一杯甜酒原文:https://blog.csdn.net/u012562943/article/details/51838759https://www.jianshu.com/p/1becdc376f5d

引言

该插件目前支持以下数据库的物理分页: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的方式进行分页。

分页插件支持MyBatis3.2.0~3.3.0(包含)

分页插件最新版本为4.1.6

使用maven方式

添加如下依赖:

代码语言:javascript
复制
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>4.1.6</version>
</dependency>

当使用maven中央库中的快照版(带"-SNAPSHOT"的版本)时,需要在pom.xml中添加如下配置:

代码语言:javascript
复制
<repositories>
    <repository>
          <id>sonatype-nexus-snapshots</id>
          <name>Sonatype Nexus Snapshots</name>
          <url>http://oss.sonatype.org/content/repositories/snapshots</url>
          <releases>
                <enabled>false</enabled>
          </releases>
          <snapshots>
                <enabled>true</enabled>
          </snapshots>
    </repository>
</repositories>

在Mybatis配置xml中配置拦截器插件:

代码语言:javascript
复制
<!-- 
    plugins在配置文件中的位置必须符合要求,否则会报错,顺序如下:
    properties?, settings?, 
    typeAliases?, typeHandlers?, 
    objectFactory?,objectWrapperFactory?, 
    plugins?, 
    environments?, databaseIdProvider?, mappers?
-->
<plugins>
    <!-- com.github.pagehelper为PageHelper类所在包名 -->
    <plugin interceptor="com.github.pagehelper.PageHelper">
        <!-- 4.0.0以后版本可以不设置该参数 -->
        <property name="dialect" value="mysql"/>
        <!-- 该参数默认为false -->
        <!-- 设置为true时,会将RowBounds第一个参数offset当成pageNum页码使用 -->
        <!-- 和startPage中的pageNum效果一样-->
        <property name="offsetAsPageNum" value="true"/>
        <!-- 该参数默认为false -->
        <!-- 设置为true时,使用RowBounds分页会进行count查询 -->
        <property name="rowBoundsWithCount" value="true"/>
        <!-- 设置为true时,如果pageSize=0或者RowBounds.limit = 0就会查询出全部的结果 -->
        <!-- (相当于没有执行分页查询,但是返回结果仍然是Page类型)-->
        <property name="pageSizeZero" value="true"/>
        <!-- 3.3.0版本可用 - 分页参数合理化,默认false禁用 -->
        <!-- 启用合理化时,如果pageNum<1会查询第一页,如果pageNum>pages会查询最后一页 -->
        <!-- 禁用合理化时,如果pageNum<1或pageNum>pages会返回空数据 -->
        <property name="reasonable" value="false"/>
        <!-- 3.5.0版本可用 - 为了支持startPage(Object params)方法 -->
        <!-- 增加了一个`params`参数来配置参数映射,用于从Map或ServletRequest中取值 -->
        <!-- 可以配置pageNum,pageSize,count,pageSizeZero,reasonable,orderBy,不配置映射的用默认值 -->
        <!-- 不理解该含义的前提下,不要随便复制该配置 -->
        <property name="params" value="pageNum=pageHelperStart;pageSize=pageHelperRows;"/>
        <!-- 支持通过Mapper接口参数来传递分页参数 -->
        <property name="supportMethodsArguments" value="false"/>
        <!-- always总是返回PageInfo类型,check检查返回类型是否为PageInfo,none返回Page -->
        <property name="returnPageInfo" value="none"/>
    </plugin>
</plugins>

这里的com.github.pagehelper.PageHelper使用完整的类路径。

其他五个参数说明:

1.增加dialect属性,使用时可以指定该属性(不指定的情况下,分页插件会自动判断),可选值为oracle、mysql、mariadb、sqlite、hsqldb、postgresql、db2、sqlserver、informix、h2、sqlserver2012。

2.增加offsetAsPageNum属性,默认值为false,使用默认值时不需要增加该配置,需要设为true时,需要配置该参数。当该参数设置为true时,使用RowBounds分页时,会将offset参数当成pageNum使用,可以用页码和页面大小两个参数进行分页。

3.增加rowBoundsWithCount属性,默认值为false,使用默认值时不需要增加该配置,需要设为true时,需要配置该参数。当该参数设置为true时,使用RowBounds分页会进行count查询。

4.增加pageSizeZero属性,默认值为false,使用默认值时不需要增加该配置,需要设为true时,需要配置该参数。当该参数设置为true时,如果pageSize=0或者RowBounds.limit = 0就会查询出全部的结果(相当于没有执行分页查询,但是返回结果仍然是Page类型)。

5.增加reasonable属性,默认值为false,使用默认值时不需要增加该配置,需要设为true时,需要配置该参数。具体作用请看上面配置文件中的注释内容。

6.为了支持startPage(Object params)方法,增加了一个params参数来配置参数映射,用于从Map或ServletRequest中取值,可以配置pageNum,pageSize,count,pageSizeZero,reasonable,orderBy,不配置映射的用默认值。

7.supportMethodsArguments支持通过Mapper接口参数来传递分页参数,默认值false,具体用法参考com.github.pagehelper.test.basic包下的ArgumentsMapTest和ArgumentsObjTest测试类。

8.returnPageInfo用来支持直接返回PageInfo类型,默认值none,可选参数always总是返回PageInfo类型,check检查返回类型是否为PageInfo,none返回Page(List)类型。用法和配置参考com.github.pagehelper.test.basic包下的PageInfoTest,特别要注意接口的返回值和xml中的resultType类型。

9.增加closeConn属性,当使用动态数据源或没有设置dialect属性自动获取数据库类型时,会自动获取一个数据库连接,通过该属性来设置是否关闭获取的这个连接,默认true关闭。

重要提示:

当offsetAsPageNum=false的时候,由于PageNum问题,RowBounds查询的时候reasonable会强制为false。使用PageHelper.startPage方法不受影响。

另外使用RowBounds在这种情况下返回的Page对象由于没有正确的pageNum属性,所以也不能使用PageInfo处理。

如果你不理解为什么,可以看这样一个例子:查询offset=7,limit=10,这个时候pageNum=?,这种情况没法计算pageNum,没法判断当前是第几页。

如何选择配置这些参数

单独看每个参数的说明可能是一件让人不爽的事情,这里列举一些可能会用到某些参数的情况。

首先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属性像下面这样配置:

代码语言:javascript
复制
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  <property name="dataSource" ref="dataSource"/>
  <property name="mapperLocations">
    <array>
      <value>classpath:mapper/*.xml</value>
    </array>
  </property>
  <property name="typeAliasesPackage" value="com.isea533.ssm.model"/>
  <property name="plugins">
    <array>
      <bean class="com.github.pagehelper.PageHelper">
        <property name="properties">
          <value>
            dialect=hsqldb
          </value>
        </property>
      </bean>
    </array>
  </property>
</bean>

属性配置按照上面的方式配置,每个配置独立一行即可。

如何在代码中使用

首先该分页插件支持以下两种调用方式:

代码语言:javascript
复制
//第一种,RowBounds方式的调用List<Country> list = sqlSession.selectList("x.y.selectIf", null, new RowBounds(1, 10));//第二种,Mapper接口方式的调用,推荐这种使用方式。PageHelper.startPage(1, 10);List<Country> list = countryMapper.selectIf(1);

下面分别对这两种方式进行详细介绍

1). RowBounds方式的调用
代码语言:javascript
复制
List<Country> list = sqlSession.selectList("x.y.selectIf", null, new RowBounds(1, 10));

使用这种调用方式时,你可以使用RowBounds参数进行分页,这种方式侵入性最小,我们可以看到,通过RowBounds方式调用只是使用了这个参数,并没有增加其他任何内容。

分页插件检测到使用了RowBounds参数时,就会对该查询进行物理分页。

关于这种方式的调用,有两个特殊的参数是针对RowBounds的,你可以参看上面的场景一和场景二

注:不只有命名空间方式可以用RowBounds,使用接口的时候也可以增加RowBounds参数,例如:

代码语言:javascript
复制
//这种情况下也会进行物理分页查询
List<Country> selectAll(RowBounds rowBounds);
2)PageHelper.startPage静态方法调用

在你需要进行分页的Mybatis方法前调用PageHelper.startPage静态方法即可,紧跟在这个方法后的第一个Mybatis查询方法会被进行分页。

例一:
代码语言:javascript
复制
SqlSession sqlSession = MybatisHelper.getSqlSession();
CountryMapper countryMapper = sqlSession.getMapper(CountryMapper.class);
try {
    //获取第1页,10条内容,默认查询总数count
    PageHelper.startPage(1, 10);

    //紧跟着的第一个select方法会被分页
    List<Country> list = countryMapper.selectIf(1);
    assertEquals(2, list.get(0).getId());
    assertEquals(10, list.size());
    //分页时,实际返回的结果list类型是Page<E>,如果想取出分页信息,需要强制转换为Page<E>,
    //或者使用PageInfo类(下面的例子有介绍)
    assertEquals(182, ((Page) list).getTotal());
} finally {
    sqlSession.close();
}
例二:
代码语言:javascript
复制
SqlSession sqlSession = MybatisHelper.getSqlSession();
CountryMapper countryMapper = sqlSession.getMapper(CountryMapper.class);
try {
    //获取第1页,10条内容,默认查询总数count
    PageHelper.startPage(1, 10);

    //紧跟着的第一个select方法会被分页
    List<Country> list = countryMapper.selectIf(1);

    //后面的不会被分页,除非再次调用PageHelper.startPage
    List<Country> list2 = countryMapper.selectIf(null);
    //list1
    assertEquals(2, list.get(0).getId());
    assertEquals(10, list.size());
    //分页时,实际返回的结果list类型是Page<E>,如果想取出分页信息,需要强制转换为Page<E>,
    //或者使用PageInfo类(下面的例子有介绍)
    assertEquals(182, ((Page) list).getTotal());
    //list2
    assertEquals(1, list2.get(0).getId());
    assertEquals(182, list2.size());
} finally {
    sqlSession.close();
}
例三,使用PageInfo的用法:
代码语言:javascript
复制
//获取第1页,10条内容,默认查询总数count
PageHelper.startPage(1, 10);
List<Country> 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集成不熟悉,可以参考下面两个

只有基础的配置信息,没有任何现成的功能,作为新手入门搭建框架的基础

  • 集成Spring3.x:
  • https://github.com/abel533/Mybatis-Spring
  • 集成Spring4.x:
  • https://github.com/abel533/Mybatis-Spring/tree/spring4

这两个集成框架集成了MyBatis分页插件和MyBatis通用Mapper。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-09-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java研发军团 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 引言
  • 使用maven方式
  • 在Mybatis配置xml中配置拦截器插件:
  • 如何选择配置这些参数
  • 4. Spring配置方法
  • 如何在代码中使用
  • MyBatis和Spring集成示例
相关产品与服务
云数据库 MariaDB
腾讯云数据库 MariaDB(TencentDB for MariaDB) 让您轻松在云端部署、使用 MariaDB 数据库。MariaDB 是在 MySQL 版权被 Oracle 收购后,由 MySQL 创始人 Monty 创立,其版权授予了“MariaDB基金会(非营利性组织)”以保证 MariaDB 永远开源,良好的开源策略,是企业级应用的最优选择,主流开源社区系统/软件的数据库系统,均已默认配置 MariaDB。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档