2017-08-11 58 views
0

考慮下面這個簡單的實體模型如何有選擇地加載休眠實體,同時還初始化(不加載)延遲集合

class Order{ 
    int id; 
    String description; 
    //one to one eager load with join column specified 
    Detail details; 
    //one to many lazy load with mapped by specified 
    Collection<Item> items; 
} 

class Detail{ 
} 

class Item{ 
    String name; 
    //reference to order 
} 

現在,讓我們說的要求是加載所有與某些標準項目的詳細信息的命令(如描述匹配的東西)。很簡單,我寫了一個hql,比如「從Order where description ...」。例如,這加載了1000個實體,並且項目集合被延遲加載。我強制通過調用大小來加載它們。

當然這導致了一個N + 1個問題,所以我決定使用批量抓取物品。只需在項目集合中添加批量大小注釋,並按預期方式添加更少的查詢。

但是,我一點都不感興趣,「細節」,但因爲它是一個一對一的渴望負荷時,有每筆訂單總是加載這個查詢。我只是想解決這些問題。

爲了解決這個問題,我嘗試做一個沒有細節的選擇,但我不知道如何在查詢中包含項目(集合),以便它以完全相同的方式加載,就像我選擇所有,然後可以在稍後的調用中使用批量大小的懶加載)。一些建議是在where子句中使用join,但是它使用空的數組列表(而不是使用PersistentBag來初始化我的集合,就像Lazy加載一樣)。

尋找解決方案。

+0

爲什麼賺不到'Detail'延遲加載的? – ujulu

+0

該應用程序的其他部分依賴於默認(急切)加載。而且,所有的解決方案都是非常簡單的(字節碼檢測等),我不想冒險打破現有的代碼。 – smi

回答

0

一個可能的解決方案是:

  • 創建一個POJO其中將包含查詢結果。例如:

    List<OrderResult> resultList = entityManager.createQuery("SELECT NEW OrderResult(o.description, i.name) FROM Order o JOIN o.items i where <condition>", OrderResult.class).getResultList(); 
    

所以你會得到只包含你感興趣的信息的OrderResult實例列表:

public class OrderResult { 
    private String description; 
    private String itemName; 
    // ... more fields, if any 

    public OrderResult(String desc, String itemName) { 
     this.description = desc; 
     this.itemName = itemName; 
    } 

    // getters & setters 
} 
  • 使用構造函數表達式作爲創建JPQL查詢。

    注1:你說的HQL,但HQL是Hibernate的特定遺留的查詢語言。由於Hibernate是JPA的實現,並且您使用JPA標記了您的問題,所以此解決方案也應該適用於您的環境。注2:在解決方案中,我使用JPQL的所謂構造函數表達式,在select子句中使用NEW定義。到NEW操作符的參數必須是一個完全合格的類名稱,例如,如果你把OrderResult類的包com.mycompany.myproject.order,則表達式應該是這樣的:

    SELECT NEW com.mycompany.myproject.order.OrderResult(...) FROM ... 
    

    注3:這只是給你提示如何實施解決方案,並應視爲pseodo代碼。

  • +0

    但是您的解決方案不考慮物品集合。我希望項目中的順序細節,據我所知,我不能在構造函數參數中包含集合。或者我錯過了什麼? – smi