MyBatis學習總結(17)——Mybatis分頁插件PageHelper

MyBatis學習總結(17)——Mybatis分頁插件PageHelper

6381人閱讀 評論(0)收藏舉報
分類:

如果你也在用Mybatis,建議嘗試該分頁插件,這一定是最方便使用的分頁插件。

分頁插件支持任何複雜的單表、多表分頁,部分特殊情況請看重要提示

想要使用分頁插件?請看如何使用分頁插件

物理分頁

該插件目前支持以下數據庫物理分頁:

  1. Oracle
  2. Mysql
  3. MariaDB
  4. SQLite
  5. Hsqldb
  6. PostgreSQL
  7. DB2
  8. SqlServer(2005,2008)
  9. Informix
  10. H2
  11. 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工具網站:http://mybatis.tk

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

分頁插件最新版本爲4.1.6

Maven座標

<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>4.1.6</version>
</dependency>

下載JAR包

分頁插件pagehelper.jar:

由於使用了sql解析工具,你還需要下載jsqlparser.jar

使用方法

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.1.6</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=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包下的ArgumentsMapTestArgumentsObjTest測試類。

  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,沒法判斷當前是第幾頁。

3. 如何選擇配置這些參數

單獨看每個參數的說明可能是一件讓人不爽的事情,這裏列舉一些可能會用到某些參數的情況。

首先dialect屬性是必須的,不需要解釋。其他的參數一般情況下我們都不必去管,如果想了解何時使用合適,你可以參考以下場景:

場景一

如果你仍然在用類似ibatis式的命名空間調用方式,你也許會用到rowBoundsWithCount,分頁插件對RowBounds支持和Mybatis默認的方式是一致,默認情況下不會進行count查詢,如果你想在分頁查詢時進行count查詢,以及使用更強大的PageInfo類,你需要設置該參數爲true

場景二

如果你仍然在用類似ibatis式的命名空間調用方式,你覺得RowBounds中的兩個參數offset,limit不如pageNum,pageSize容易理解,你可以使用offsetAsPageNum參數,將該參數設置爲true後,offset會當成pageNum使用,limitpageSize含義相同。

場景三

如果覺得某個地方使用分頁後,你仍然想通過控制參數查詢全部的結果,你可以配置pageSizeZerotrue,配置後,如可以通過設置pageSize=0或者RowBounds.limit = 0就會查詢出全部的結果。

場景四

如果你分頁插件使用於類似分頁查看列表式的數據,如新聞列表,軟件列表,你希望用戶輸入的頁數不在合法範圍(第一頁到最後一頁之外)時能夠正確的響應到正確的結果頁面,那麼你可以配置reasonabletrue,這時如果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屬性像下面這樣配置:

<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>

屬性配置按照上面的方式配置,每個配置獨立一行即可。

5. 如何在代碼中使用

閱讀前後請注意看重要提示

首先該分頁插件支持以下兩種調用方式:

//第一種,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方式的調用

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<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();
}
例二:
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的用法:
//獲取第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());

本項目中包含大量測試,您可以通過查看測試代碼瞭解使用方法。

測試代碼地址:http://git.oschina.net/free/Mybatis_PageHelper/tree/master/src/test/java/com/github/pagehelper/test

MyBatis和Spring集成示例

如果和Spring集成不熟悉,可以參考下面兩個

只有基礎的配置信息,沒有任何現成的功能,作爲新手入門搭建框架的基礎

這兩個集成框架集成了MyBatis分頁插件和MyBatis通用Mapper。


0
0

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章