2011-01-27 45 views
5

對象的結構是這樣的在Hibernate中檢索圖形結構

  • 發票
    • 客戶
    • 日期
    • 有很多代理產品(產品,數量,價格)
    • 有很多ServiceLines(服務,數量,價格)
    • 有很多PaymentOptions(PaymentType(支票,收據等),日期,和)

如果我需要找回發票的列表與Hibernate一定時期內是很容易做到的懶無需編寫任何代碼就可以調用get ...但是有太多數據庫調用的缺點,所以在多用戶環境中,這種解決方案並不好。

使用普通JDBC我使用3個查詢解決了這個問題:在Invoice和ProductLines,Invoice和ServiceLines以及發票和付款選項之間的3個連接。之後,我在內存中構建了這個對象。

可以用Hibernate做同樣的事我知道但是我的問題是沒有這樣的東西,因爲我可以通過發票列表和最少數量的調用(最佳的) 檢索數據?

回答

4

您可以使用查詢與連接抓取來獲得整個對象圖到內存:

Query query = entityManager.createQuery("select distinct invoice from Invoice as invoice " 
      + "left join fetch invoice.productLines "     
      + "left join fetch invoice.serviceLines " 
      + "left join fetch invoice.paymentOptions"); 
for (Object object : query.getResultList()) { 
    // Code here 
} 
4

您可能會考慮使用batch fetching作爲您的發票行,併爲多對一的關聯(例如客戶)提前獲取。

這會不會讓你到一個數據庫調用,但如果你調你的批量略超過發票每種類型的線的平均數量,那麼你可以靜下心來,每行一個類型。

你也可以查詢中使用JPQL/HQL,並明確取指令 - 參加行(as Russ decribes),但你得到一個較大的結果比你會與一個批量抓取方式設置:

Query query = entityManager.createQuery("select distinct invoice from Invoice as invoice " 
      + "left join fetch invoice.productLines "     
      + "left join fetch invoice.serviceLines " 
      + "left join fetch invoice.paymentOptions"); 
for (Object object : query.getResultList()) { 
    // Code here 
} 

如果大小的傳輸的原始數據證明過高,則可以通過從相關位置的查詢中刪除「獲取」來禁用顯式提取。

請注意,使用JPQL會導致維護問題,因爲編譯器無法爲您檢查所有屬性名稱,並且如果所有關聯的提取都關閉,則查詢是淨成本。如果性能不是直接問題,您可能希望從批量抓取開始。

+0

你把我在正確的方向(可惜的是我不能給你一個了投票,因爲我不允許尚未)。謝謝 – Cris 2011-01-27 11:01:53

+1

命名查詢可用於解決屬性名稱問題 - 它們可以在單元測試中輕鬆檢查。運行時查詢只是爲了縮小示例 - 應始終使用命名查詢。 – 2011-01-27 16:12:00