一、問題現象
在mybatis的resultMap標簽中使用collection或者assocation做嵌套結果映射,再配合PageHalper實現分頁效果的時候,會出現兩個問題:
-
實際查出來的數據,會部分丟失,比如傳的頁面大小是10條,那么有可能會返回小於10條記錄。 -
分頁對象的total總數與實際返回的數量不一致。
二、問題原因
在定位問題前,我們先了解下PageHalper的工作原理,PageHapler主要是通過攔截器實現的,在執行sql前會根據頁碼和頁數在sql的后面加上關鍵字,比如limit,rownum等。
在PageHapler攔截SQL添加分頁關鍵字成功后,由於嵌套結果集的方式會導致結果集被折疊,因此分頁查詢后的結果在折疊后總數會減少,所以無法保證分頁結果數量正確。
在PageHapler官網的常見問題列表中也有對此問題的說明:
為什么不支持一對一和一對多結果映射的分頁查詢?
在一對一和一對多時,根據分頁條件查詢出 100 條數據時,由於一對一和一對多會去重,經過嵌套處理后數據量會減少,因此分頁想要獲得 100 條數據無法實現。想要支持這種情況可以使用嵌套查詢。嵌套查詢是要額外執行SQL,主SQL可以得到正確的結果數量,因此可以正常分頁。
三、解決方法
-
使用mybatis的嵌套查詢,在resultMap的collection標簽中使用select屬性額外執行SQL,如果數據量比較大的時候,可能對性能影響嚴重。
<resultMap id="list" type="com.xxx.xxx.entity.xxxxxxx">
<id column="id_" property="id"/>
<result column="name_" property="name"/>
<collection property="users"
javaType="java.util.ArrayList"
ofType="com.xxx.xxx.xxx.xxx"
select="com.xxx.xxx.xxx.xxx.xxxx"
column="{id=id_}"/>
</resultMap> -
在業務層service中,拿到主SQL的結果集,再傳入條件去執行額外SQL獲取結果集。