1. 程式人生 > 其它 >Mybatis collection標籤配合PageHapler分頁問題

Mybatis collection標籤配合PageHapler分頁問題

一、問題現象

在mybatis的resultMap標籤中使用collection或者assocation做巢狀結果對映,再配合PageHalper實現分頁效果的時候,會出現兩個問題:

  1. 實際查出來的資料,會部分丟失,比如傳的頁面大小是10條,那麼有可能會返回小於10條記錄。
  2. 分頁物件的total總數與實際返回的數量不一致。

二、問題原因

在定位問題前,我們先了解下PageHalper的工作原理,PageHapler主要是通過攔截器實現的,在執行sql前會根據頁碼和頁數在sql的後面加上關鍵字,比如limit,rownum等。

在PageHapler攔截SQL新增分頁關鍵字成功後,由於巢狀結果集的方式會導致結果集被摺疊,因此分頁查詢後的結果在摺疊後總數會減少,所以無法保證分頁結果數量正確。

在PageHapler官網的常見問題列表中也有對此問題的說明:

為什麼不支援一對一和一對多結果對映的分頁查詢?

在一對一和一對多時,根據分頁條件查詢出 100 條資料時,由於一對一和一對多會去重,經過巢狀處理後資料量會減少,因此分頁想要獲得 100 條資料無法實現。想要支援這種情況可以使用巢狀查詢。巢狀查詢是要額外執行SQL,主SQL可以得到正確的結果數量,因此可以正常分頁。

三、解決方法

  1. 使用mybatis的巢狀查詢,在resultMap的collection標籤中使用select屬性額外執行SQL,如果資料量比較大的時候,可能對效能影響嚴重。

    <resultMapid="list"type
    ="com.xxx.xxx.entity.xxxxxxx">

    <idcolumn="id_"property="id"/>
    <resultcolumn="name_"property="name"/>
    <collectionproperty="users"
    javaType="java.util.ArrayList"
    ofType="com.xxx.xxx.xxx.xxx"
    select="com.xxx.xxx.xxx.xxx.xxxx"
    column="{id=id_}"/>

    </resultMap>
  2. 在業務層service中,拿到主SQL的結果集,再傳入條件去執行額外SQL獲取結果集。

You have a dream, you got to protect it.