• UID297
  • 登录2017-07-17
  • 粉丝44
  • 关注112
  • 发帖277
  • 主页http://weibo.com/2619518393/
  • 金币1536枚
喜欢达人
社区居民
最爱沙发
忠实会员
原创写手
追星一族
jkxqj 发布于2015-11-25 15:19
3/1917

Mybatis分页插件

楼层直达
使用方法

1. 引入分页插件

引入分页插件一共有下面2种方式,推荐使用Maven方式,这种方式方便更新。

1). 引入Jar包

如果你想使用本项目的jar包而不是直接引入类,你可以在这里下载各个版本的jar包(点击Download下的jar即可下载)由于使用了sql解析工具,你还需要下载jsqlparser.jar(这个文件完全独立,不依赖其他):
2). 使用maven

添加如下依赖:
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>4.0.1</version>
</dependency>

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

2. 在Mybatis配置xml中配置拦截器插件:
<!-- 
    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=start;pageSize=limit;"/>
        <!-- 支持通过Mapper接口参数来传递分页参数 -->
        <property name="supportMethodsArguments" value="true"/>
        <!-- always总是返回PageInfo类型,check检查返回类型是否为PageInfo,none返回Page -->
        <property name="returnPageInfo" value="check"/>
    </plugin>
</plugins>
这里的com.github.pagehelper.PageHelper使用完整的类路径。其他五个参数说明:
  1. 增加dialect属性,使用时可以指定该属性(不指定的情况下,分页插件会自动判断),可选值为oracle,mysql,mariadb,sqlite,hsqldb,postgresql,db2,sqlserver,informix。
  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接口参数来传递分页参数,具体用法参考com.github.pagehelper.test.basic包下的ArgumentsMapTest和ArgumentsObjTest测试类。
  8. returnPageInfo用来支持直接返回PageInfo类型,可选参数always总是返回PageInfo类型,check检查返回类型是否为PageInfo,none返回Page(List)类型。用法和配置参考com.github.pagehelper.test.basic包下的PageInfoTest,特别要注意接口的返回值和xml中的resultType类型。
重要提示:当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属性像下面这样配置:
&lt;bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"&gt;
  &lt;property name="dataSource" ref="dataSource"/&gt;
  &lt;property name="mapperLocations"&gt;
    &lt;array&gt;
      &lt;value&gt;classpath:mapper/*.xml&lt;/value&gt;
    &lt;/array&gt;
  &lt;/property&gt;
  &lt;property name="typeAliasesPackage" value="com.isea533.ssm.model"/&gt;
  &lt;property name="plugins"&gt;
    &lt;array&gt;
      &lt;bean class="com.github.pagehelper.PageHelper"&gt;
        &lt;property name="properties"&gt;
          &lt;value&gt;
            dialect=hsqldb
          &lt;/value&gt;
        &lt;/property&gt;
      &lt;/bean&gt;
    &lt;/array&gt;
  &lt;/property&gt;
&lt;/bean&gt;

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

5. 如何在代码中使用

阅读前后请注意看重要提示首先该分页插件支持以下两种调用方式:
//第一种,RowBounds方式的调用
List&lt;Country&gt; list = sqlSession.selectList("x.y.selectIf", null, new RowBounds(1, 10));
    
//第二种,Mapper接口方式的调用,推荐这种使用方式。
PageHelper.startPage(1, 10);
List&lt;Country&gt; list = countryMapper.selectIf(1);
下面分别对这两种方式进行详细介绍


1). RowBounds方式的调用



List<Country> list = sqlSession.selectList("x.y.selectIf", null, new RowBounds(1, 10));



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



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








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



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








//这种情况下也会进行物理分页查询



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

本项目中包含大量测试,您可以通过查看测试代码了解使用方法。测试代码地址:http://git.oschina.net/free/Mybatis_PageHelper/tree/master/src/test/java/com/github/pagehelper/test

MyBatis和Spring集成示例

如果和Spring集成不熟悉,可以参考下面两个只有基础的配置信息,没有任何现成的功能,作为新手入门搭建框架的基础这两个集成框架集成了MyBatis分页插件和MyBatis通用Mapper。


原文来自:http://git.oschina.net/free/Mybatis_PageHelper
欢迎关注我的微信公众号:oldriverNote

0人打赏
  • UID297
  • 登录2017-07-17
  • 粉丝44
  • 关注112
  • 发帖277
  • 主页http://weibo.com/2619518393/
  • 金币1536枚
喜欢达人
社区居民
最爱沙发
忠实会员
原创写手
追星一族
jkxqj 发布于2015-11-29 12:08
沙发F
沙发
欢迎关注我的微信公众号:oldriverNote
  • UID15
  • 登录2017-07-17
  • 粉丝48
  • 关注40
  • 发帖447
  • 主页
  • 金币1844枚
社区居民
喜欢达人
原创写手
janking 发布于2015-11-30 10:25
板凳F
那我抢个板凳
  • UID1752
  • 登录2015-12-23
  • 粉丝0
  • 关注0
  • 发帖10
  • 主页
  • 金币12枚
清醒i 发布于2015-12-23 17:03
地板F
感谢楼主分享
您需要登录后才可以回帖
发表回复
极贡献
技术问答
专题荟萃
程序人生
视觉设计
Android开发
iOS开发
编程语言
前端开发
后端开发
服务器架构
软件测试
运维方案
创业路上



最热文章墙

  • 72653/370   【精品推荐】200多种Android动画效果的强悍框架,太全了,不看这个,再有动画的问题,不理你了^@^

  • 41448/0   Python爬虫:常用浏览器的useragent

  • 41434/191   情人节福利,程序员表白的正确姿势:改几行代码就变成自己的表白了

  • 37939/259   【精品推荐】Android版产品级的音乐播放器源码,功能太强大了,最好的产品原型有木有?

  • 36492/145   省时省力的Android组件群来了,非常棒的原型参考

  • 28429/2   超全!整理常用的iOS第三方资源

  • 27900/71   原创表白APP,以程序员的姿势备战新年后的7夕,持续完善中!

  • 27791/142   2016抢红包软件及源码

  • 22080/30   麻省理工的一帮疯子,真的实现了随意操控万物!(绝对黑科技)

  • 21897/157   Android版类似UC浏览器:非常赞,产品级的源码

  • 21695/25   Android工程师面试题大全

  • 21539/27   2016程序员跳槽全攻略

  • 21362/9   GitHub上排名前50的iOS项目:总有一款你用得着

  • 20243/20   码魂:程序员的牛B漫画

  • 18445/10   2016年最全的Android面试考题+答案 精编版

  • 18192/3   吐槽那些程序员的搞笑牛逼注释

  • 17825/42   一个绚丽的loading动效分析与实现!

  • 17723/73   【持续更新中】Android福利贴(二):资料源码大放送

  • 17706/85   Android小而全的博客源码:非常适合全面掌握开发技巧

  • 17119/1   iOS 动画总结

  • 16605/45   惊艳的App引导页:背景图片切换加各个页面动画效果

  • 16307/23   个人收集的Android 各类功能源代码

  • 16130/81   仿京东商城客户端Android最新版,不错的原型和学习资料

  • 15948/10   女程序员的梦,众网友的神回复

  • 15843/5   新一代Android渠道打包工具:1000个渠道包只需要5秒

  • 15735/104   Android带弹幕的视频播放器源码,来自大名鼎鼎的Bilibili弹幕网站

  • 15644/11   年会上现场review代码是怎么样的体验!

  • 15527/21   Android福利第三波【Android电子书】

  • 15445/17   用JavaScript 来开发iOS和Android 原生应用:React Native开源框架中文版来啦

  • 15438/53   基于瀑布流的美女图片浏览App,有注释的源代码

  • 15257/23   珍藏多年的素材,灵感搜寻网站

  • 15063/79   【精品推荐】类似360安全卫士安Android源码:非常赞的产品原型

  • 14886/0   iOS中文版资源库,非常全

  • 14513/18   65条最常用正则表达式,你要的都在这里了

  • 14210/15   基于Android支付宝支付设计和开发方案

  • 13674/17   什么是真正的黑客:收获12200+Stars,人气远超微软开源VS

  • 13475/11   有木有这样一张酷图帮你集齐所有git命令超实用

  • 13036/46   在线音乐播放器完整版(商用级的源码):非常赞,可听免费高品质专辑

  • 13020/7   一张图搞定iOS学习路线,非常全面

  • 12937/7   用程序员的姿势抢过年的火车票

  • 12915/0   GitHub iOS 库和框架Top100 

  • 12643/10   成为Java顶尖程序员 ,看这11本书就够了

  • 12517/10   微信支付终于成功了(安卓,iOS),在此分享

  • 12465/18   一张图搞定Android学习路线,非常全面

  • 12323/61   【技巧一】搭配Android Studio,如何实现App远程真机debug?

  • 12131/3   基于Node.js的强大爬虫,能直接发布抓取的文章哦

  • 12078/29   【持续更新中】Android福利贴(一):资料源码

  • 11518/4   46 个非常有用的 PHP 代码片段

  • 11278/3   即时通信第三方库

  • 10890/8   流媒体视频直播方案

  • 10785/18   八个最优秀的Android Studio插件

  • 10743/9   B站建开源工作组:APP想支持炫酷弹幕的看过来

  • 10613/9   烧了5亿美金,这家神秘的公司即将颠覆人类未来!

  • 10467/2   【精品推荐】高质量PHP代码的50个实用技巧:非常值得收藏

  • 10407/10   中国黑客的隐秘江湖:攻守对立,顶尖高手月入千万美元

  • 9793/6   开箱即用!Android四款系统架构工具

  • 9596/10   十大技巧快速提升Android应用开发性能

  • 9532/3   10款GitHub上最火爆的国产开源项目——可以媲美西半球

  • 9457/3   一张图看清Linux 内核运行原理

  • 9359/1   Android性能优化视频,文档以及工具

  • 返回顶部