簡體   English   中英

JPA實體圖和分頁

[英]JPA entity graphs and pagination

在我當前的項目中,我們在系統中有多個搜索頁面,我們從數據庫中獲取大量數據,以便在UI中的大表元素中顯示。 我們使用JPA進行數據訪問(我們的提供程序是Hibernate)。 大多數頁面的數據是從多個數據庫表中收集的 - 在許多情況下大約10個 - 包括來自OneToMany關系的一些聚合數據(例如“類型X的關聯實體的數量”)。 為了提高性能,我們使用TypedQuery.setFirstResult()TypedQuery.setMaxResults()結果集分頁,在用戶滾動表時從數據庫中延遲加載其他行。 由於搜索非常動態,我們使用JPA CriteriaQuery API來構建查詢。 但是,我們目前有點受到N + 1 SELECT問題的困擾。 實際上在某些情況下非常糟糕,因為我們可能會迭代3級嵌套的OneToMany關系,其中每個級別的數據都是延遲加載的。 我們無法真正將這些集合聲明為在實體映射中加載,因為我們只對它們的某些頁面感興趣。 也就是說,我們可以在幾個不同的頁面中從同一個表中獲取數據,但是我們在表中以及不同頁面中的不同關聯表中顯示不同的數據。

為了緩解這種情況,我們開始嘗試使用JPA實體圖,它們似乎對N + 1 SELECT問題有很大幫助。 但是,當您使用實體圖時,Hibernate顯然會在內存中應用分頁。 我可以理解為什么會這樣做,但在許多情況下,這種行為否定了實體圖的很多(如果不是全部)好處。 當我們不使用實體圖時,我們可以在不應用任何WHERE限制的情況下加載數據(即將整個表視為結果集),無論表有多少行,因為只有非常有限的行數。實際上由於分頁而獲取。 既然分頁是在內存中完成的,Hibernate基本上會獲取整個數據庫表(加上實體圖中定義的所有關系),然后在內存中應用分頁,將剩下的行拋棄。 不好。

所以問題是, 有沒有一種有效的方法來應用JPA(Hibernate)的分頁和實體圖? 如果JPA沒有提供解決方案,那么Hibernate特定的擴展也是可以接受的。 如果那也不可能,那么其​​他選擇是什么? 使用數據庫視圖? 由於我們支持多個數據庫供應商,因此視圖會有點麻煩。 為不同的供應商創建所有必要的視圖會增加開發工作量。

我所擁有的另一個想法是應用實體圖和分頁,就像我們目前所做的那樣,如果它們返回太多行,就不會觸發任何查詢。 我已經需要執行COUNT個查詢以使延遲加載的行在UI中正常工作。

我不確定我是否完全理解您的問題,但我們遇到了類似的問題:我們已經分頁了可能包含來自多個連接實體的數據的實體列表。 這些列表可能會被排序和過濾(由於dbms中的缺失功能,這些排序/過濾器中的一些必須在內存中應用,但這只是一個附注),之后應該應用分頁。

將所有數據保存在內存中並不能很好地工作,因此我們采用了以下方法(可能有更好/更標准的方法):

  1. 使用查詢加載主要實體的主鍵(在我們的例子中是簡單的long)。 僅加入排序和過濾所需的內容,以使查詢盡可能簡單。

    在我們的例子中,查詢實際上會加載更多數據,以便在必要時在內存中應用排序和過濾器,但是數據會盡快釋放,並且只保留主鍵。
  2. 當顯示特定頁面時,我們提取頁面的相應主鍵,並使用第二個查詢來加載要在該頁面上顯示的所有內容。 第二個查詢可能包含更多連接,因此比步驟1中的更復雜和更慢,但由於我們只加載該頁面的數據,因此系統的實際負擔非常低。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM