欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Mybatis分頁插件PageHelper的配置和簡單使用方法(推薦)

 更新時間:2017年12月08日 11:49:25   作者:扎心了老鐵  
在使用Java Spring開發(fā)的時候,Mybatis算是對數(shù)據(jù)庫操作的利器了。這篇文章主要介紹了Mybatis分頁插件PageHelper的配置和使用方法,需要的朋友可以參考下

前言

在web開發(fā)過程中涉及到表格時,例如dataTable,就會產(chǎn)生分頁的需求,通常我們將分頁方式分為兩種:前端分頁和后端分頁。

前端分頁

一次性請求數(shù)據(jù)表格中的所有記錄(ajax),然后在前端緩存并且計算count和分頁邏輯,一般前端組件(例如dataTable)會提供分頁動作。

特點(diǎn)是:簡單,很適合小規(guī)模的web平臺;當(dāng)數(shù)據(jù)量大的時候會產(chǎn)生性能問題,在查詢和網(wǎng)絡(luò)傳輸?shù)臅r間會很長。

后端分頁

在ajax請求中指定頁碼(pageNum)和每頁的大小(pageSize),后端查詢出當(dāng)頁的數(shù)據(jù)返回,前端只負(fù)責(zé)渲染。

特點(diǎn)是:復(fù)雜一些;性能瓶頸在MySQL的查詢性能,這個當(dāng)然可以調(diào)優(yōu)解決。一般來說,web開發(fā)使用的是這種方式。

我們說的也是后端分頁。

MySQL對分頁的支持

簡單來說MySQL對分頁的支持是通過limit子句。請看下面的例子。

limit關(guān)鍵字的用法是

LIMIT [offset,] rows

offset是相對于首行的偏移量(首行是0),rows是返回條數(shù)。

# 每頁10條記錄,取第一頁,返回的是前10條記錄
select * from tableA limit 0,10;
# 每頁10條記錄,取第二頁,返回的是第11條記錄,到第20條記錄,
select * from tableA limit 10,10;

這里提一嘴的是,MySQL在處理分頁的時候是這樣的:

limit 1000,10 - 過濾出1010條數(shù)據(jù),然后丟棄前1000條,保留10條。當(dāng)偏移量大的時候,性能會有所下降。

limit 100000,10 - 會過濾10w+10條數(shù)據(jù),然后丟棄前10w條。如果在分頁中發(fā)現(xiàn)了性能問題,可以根據(jù)這個思路調(diào)優(yōu)。

Mybatis分頁插件PageHelper

在使用Java Spring開發(fā)的時候,Mybatis算是對數(shù)據(jù)庫操作的利器了。不過在處理分頁的時候,Mybatis并沒有什么特別的方法,一般需要自己去寫limit子句實現(xiàn),成本較高。好在有個PageHelper插件。

1、POM依賴

Mybatis的配置就不多提了。PageHelper的依賴如下。需要新的版本可以去maven上自行選擇

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

2、Mybatis對PageHelper的配置

打開Mybatis配置文件,一般在Resource路徑下。我這里叫mybatis-config.xml。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 全局參數(shù) -->
<settings>
  <!-- 使全局的映射器啟用或禁用緩存。 -->
  <setting name="cacheEnabled" value="true"/>
  <!-- 全局啟用或禁用延遲加載。當(dāng)禁用時,所有關(guān)聯(lián)對象都會即時加載。 -->
  <setting name="lazyLoadingEnabled" value="true"/>
  <!-- 當(dāng)啟用時,有延遲加載屬性的對象在被調(diào)用時將會完全加載任意屬性。否則,每種屬性將會按需要加載。 -->
  <setting name="aggressiveLazyLoading" value="true"/>
  <!-- 是否允許單條sql 返回多個數(shù)據(jù)集 (取決于驅(qū)動的兼容性) default:true -->
  <setting name="multipleResultSetsEnabled" value="true"/>
  <!-- 是否可以使用列的別名 (取決于驅(qū)動的兼容性) default:true -->
  <setting name="useColumnLabel" value="true"/>
  <!-- 允許JDBC 生成主鍵。需要驅(qū)動器支持。如果設(shè)為了true,這個設(shè)置將強(qiáng)制使用被生成的主鍵,有一些驅(qū)動器不兼容不過仍然可以執(zhí)行。 default:false -->
  <setting name="useGeneratedKeys" value="true"/>
  <!-- 指定 MyBatis 如何自動映射 數(shù)據(jù)基表的列 NONE:不隱射 PARTIAL:部分 FULL:全部 -->
  <setting name="autoMappingBehavior" value="PARTIAL"/>
  <!-- 這是默認(rèn)的執(zhí)行類型 (SIMPLE: 簡單; REUSE: 執(zhí)行器可能重復(fù)使用prepared statements語句;BATCH: 執(zhí)行器可以重復(fù)執(zhí)行語句和批量更新) -->
  <setting name="defaultExecutorType" value="SIMPLE"/>
  <!-- 使用駝峰命名法轉(zhuǎn)換字段。 -->
  <setting name="mapUnderscoreToCamelCase" value="true"/>
  <!-- 設(shè)置本地緩存范圍 session:就會有數(shù)據(jù)的共享 statement:語句范圍 (這樣就不會有數(shù)據(jù)的共享 ) defalut:session -->
  <setting name="localCacheScope" value="SESSION"/>
  <!-- 設(shè)置但JDBC類型為空時,某些驅(qū)動程序 要指定值,default:OTHER,插入空值時不需要指定類型 -->
  <setting name="jdbcTypeForNull" value="NULL"/>
</settings>
<plugins>
  <plugin interceptor="com.github.pagehelper.PageHelper">
    <property name="dialect" value="mysql"/>
    <property name="offsetAsPageNum" value="false"/>
    <property name="rowBoundsWithCount" value="false"/>
    <property name="pageSizeZero" value="true"/>
    <property name="reasonable" value="false"/>
    <property name="supportMethodsArguments" value="false"/>
    <property name="returnPageInfo" value="none"/>
  </plugin>
</plugins>
</configuration>  

這里要注意的是PageHelper相關(guān)的配置。

如果你沒有加載Mybatis配置文件,那么使用的是Mybatis默認(rèn)的配置。如何加載Mybatis配置文件呢?

到你的dataSrouce配置中。

在配置sqlSessionFactory的時候,指定Mybatis核心配置文件和mapper的路徑,代碼如下

@Bean(name = "moonlightSqlSessionFactory")
  @Primary
  public SqlSessionFactory moonlightSqlSessionFactory(@Qualifier("moonlightData") DataSource dataSource) throws Exception {
    SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
    bean.setDataSource(dataSource);
    bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mybatis-mapper/*.xml"));
    bean.setConfigLocation(new ClassPathResource("mybatis-config.xml"));
    return bean.getObject();
  }  

 說明:

這里配置的mapper.xml存放路徑,在Resource/mybatis-mapper文件夾下

這里配置的mybatis-config.xml文件,在Resource/下

3、分頁

準(zhǔn)備一個mapper.xml,測試就隨便寫一個吧,干脆就用工程里的一個。

這里這個查詢,是一個典型的多條件查詢,我們要做的是對多條件匹配到的記錄進(jìn)行分頁。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.kangaroo.studio.moonlight.dao.mapper.MoonlightMapper">
 <resultMap id="geoFenceList" type="com.kangaroo.studio.moonlight.dao.model.GeoFence">
  <constructor>
   <idArg column="id" javaType="java.lang.Integer" jdbcType="INTEGER" />
   <arg column="name" javaType="java.lang.String" jdbcType="VARCHAR" />
   <arg column="type" javaType="java.lang.Integer" jdbcType="INTEGER" />
   <arg column="group" javaType="java.lang.String" jdbcType="VARCHAR" />
   <arg column="geo" javaType="java.lang.String" jdbcType="VARCHAR" />
   <arg column="createTime" javaType="java.lang.String" jdbcType="VARCHAR" />
   <arg column="updateTime" javaType="java.lang.String" jdbcType="VARCHAR" />
  </constructor>
 </resultMap>
 <sql id="base_column">id, name, type, `group`, geo, createTime, updateTime </sql>
 <select id="queryGeoFence" parameterType="com.kangaroo.studio.moonlight.dao.model.GeoFenceQueryParam" resultMap="geoFenceList">
  select <include refid="base_column"/> from geoFence where 1=1
  <if test="type != null">
   and type = #{type}
  </if>
  <if test="name != null">
   and name like concat('%', #{name},'%')
  </if>
  <if test="group != null">
   and `group` like concat('%', #{group},'%')
  </if>
  <if test="startTime != null">
   and createTime >= #{startTime}
  </if>
  <if test="endTime != null">
   and createTime <= #{endTime}
  </if>
 </select>
</mapper>

在Mapper.java接口中編寫對應(yīng)的方法

List<GeoFence> queryGeoFence(GeoFenceQueryParam geoFenceQueryParam);

先上分頁代碼,后面再說明      

@RequestMapping(value = "/fence/query", method = RequestMethod.POST)
  @ResponseBody
  public Response queryFence(@RequestBody GeoFenceQueryParam geoFenceQueryParam) {
    try {
      Integer pageNum = geoFenceQueryParam.getPageNum()!=null?geoFenceQueryParam.getPageNum():1;
      Integer pageSize = geoFenceQueryParam.getPageSize()!=null?geoFenceQueryParam.getPageSize():10;
      PageHelper.startPage(pageNum, pageSize);
      List<GeoFence> list = moonlightMapper.queryGeoFence(geoFenceQueryParam);
      return new Response(ResultCode.SUCCESS, "查詢geoFence成功", list);
    } catch (Exception e) {
      logger.error("查詢geoFence失敗", e);
      return new Response(ResultCode.EXCEPTION, "查詢geoFence失敗", null);
    }
  }

說明:

1、PageHelper的優(yōu)點(diǎn)是,分頁和Mapper.xml完全解耦。實現(xiàn)方式是以插件的形式,對Mybatis執(zhí)行的流程進(jìn)行了強(qiáng)化,添加了總數(shù)count和limit查詢。屬于物理分頁。

2、有一個安全性問題,需要注意一下,不然可能導(dǎo)致分頁錯亂。我這里直接粘貼了這篇博客里的一段話。

4. 什么時候會導(dǎo)致不安全的分頁?

PageHelper 方法使用了靜態(tài)的 ThreadLocal 參數(shù),分頁參數(shù)和線程是綁定的。

只要你可以保證在 PageHelper 方法調(diào)用后緊跟 MyBatis 查詢方法,這就是安全的。因為 PageHelper 在 finally 代碼段中自動清除了 ThreadLocal 存儲的對象。

如果代碼在進(jìn)入 Executor 前發(fā)生異常,就會導(dǎo)致線程不可用,這屬于人為的 Bug(例如接口方法和 XML 中的不匹配,導(dǎo)致找不到 MappedStatement 時), 這種情況由于線程不可用,也不會導(dǎo)致 ThreadLocal 參數(shù)被錯誤的使用。

但是如果你寫出下面這樣的代碼,就是不安全的用法:

PageHelper.startPage(1, 10);
List<Country> list;
if(param1 != null){
  list = countryMapper.selectIf(param1);
} else {
  list = new ArrayList<Country>();
}

這種情況下由于 param1 存在 null 的情況,就會導(dǎo)致 PageHelper 生產(chǎn)了一個分頁參數(shù),但是沒有被消費(fèi),這個參數(shù)就會一直保留在這個線程上。當(dāng)這個線程再次被使用時,就可能導(dǎo)致不該分頁的方法去消費(fèi)這個分頁參數(shù),這就產(chǎn)生了莫名其妙的分頁。

上面這個代碼,應(yīng)該寫成下面這個樣子:

List<Country> list;
if(param1 != null){
  PageHelper.startPage(1, 10);
  list = countryMapper.selectIf(param1);
} else {
  list = new ArrayList<Country>();
}

這種寫法就能保證安全。

如果你對此不放心,你可以手動清理 ThreadLocal 存儲的分頁參數(shù),可以像下面這樣使用:

List<Country> list;
if(param1 != null){
  PageHelper.startPage(1, 10);
  try{
    list = countryMapper.selectAll();
  } finally {
    PageHelper.clearPage();
  }
} else {
  list = new ArrayList<Country>();
}

這么寫很不好看,而且沒有必要。

總結(jié)

以上所述是小編給大家介紹的Mybatis分頁插件PageHelper的配置和簡單使用方法(推薦),希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!

相關(guān)文章

  • 自定義BufferedReader的實例

    自定義BufferedReader的實例

    下面小編就為大家分享一篇自定義BufferedReader的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2017-12-12
  • java?class?name實例深入精講

    java?class?name實例深入精講

    這篇文章主要為大家介紹了java?class?name實例深入精講,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-09-09
  • 在springboot中使用p6spy方式

    在springboot中使用p6spy方式

    這篇文章主要介紹了在springboot中使用p6spy方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • Java超詳細(xì)介紹封裝與訪問控制修符

    Java超詳細(xì)介紹封裝與訪問控制修符

    封裝是一個非常廣泛的概念,小到一個屬性的封裝,大到一個框架或者一個項目的封裝,文中通過實例代碼將詳細(xì)介紹封裝與訪問控制修飾符
    2022-05-05
  • Java項目中如何引入Hutool工具類并正確使用它

    Java項目中如何引入Hutool工具類并正確使用它

    Hutool是一個小而全的Java工具類庫,通過靜態(tài)方法封裝,降低相關(guān)API的學(xué)習(xí)成本,提高工作效率,使Java擁有函數(shù)式語言般的優(yōu)雅,這篇文章主要給大家介紹了關(guān)于Java項目中如何引入Hutool工具類并正確使用它的相關(guān)資料,需要的朋友可以參考下
    2024-01-01
  • Java中dubbo+zookeeper微服務(wù)架構(gòu)簡介

    Java中dubbo+zookeeper微服務(wù)架構(gòu)簡介

    Apache Dubbo是一款高性能的 Java RPC 框架,這篇文章主要介紹了Java中dubbo+zookeeper微服務(wù)架構(gòu),需要的朋友可以參考下
    2021-09-09
  • springboot+kafka中@KafkaListener動態(tài)指定多個topic問題

    springboot+kafka中@KafkaListener動態(tài)指定多個topic問題

    這篇文章主要介紹了springboot+kafka中@KafkaListener動態(tài)指定多個topic問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • 值得Java程序猿閱讀的書籍

    值得Java程序猿閱讀的書籍

    這篇文章主要推薦了一些值得Java程序猿閱讀的書籍,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • Java中List與數(shù)組之間的相互轉(zhuǎn)換

    Java中List與數(shù)組之間的相互轉(zhuǎn)換

    在日常Java學(xué)習(xí)或項目開發(fā)中,經(jīng)常會遇到需要int[]數(shù)組和List列表相互轉(zhuǎn)換的場景,然而往往一時難以想到有哪些方法,最后可能會使用暴力逐個轉(zhuǎn)換法,往往不是我們所滿意的,下面這篇文章主要給大家介紹了關(guān)于Java中List與數(shù)組之間的相互轉(zhuǎn)換,需要的朋友可以參考下
    2023-05-05
  • java微信開發(fā)API第一步 服務(wù)器接入

    java微信開發(fā)API第一步 服務(wù)器接入

    這篇文章主要為大家分享了java微信開發(fā)API的第一步操作服務(wù)器接入,感興趣的小伙伴們可以參考一下
    2016-05-05

最新評論