2012-04-25 108 views
14

即時通訊使用休眠3寫一個Web應用程序。休眠性能最佳實踐?

所以,過了一段時間,我發現有些東西很慢。所以我測試了hibernate profiler,發現hibernate會爲簡單操作做出不合理的多個db調用。原因是我加載一個對象(這個對象有幾個「父母」),這些「父母」有其他「父母」。所以基本上hibernate加載它們,即使我只需要基本對象。好吧,所以我看着懶加載。這導致我進入Lazyloading-exception,因爲我有一個MVC webapp。

所以,現在我有點困惑,什麼是我最好的辦法。 基本上我需要的是更新對象上的單個字段。我已經有了對象鍵。

應該我: 1.挖掘延遲加載。然後重寫我的應用程序以獲得開放會話視圖? 2.挖掘延遲加載。然後重寫我的道是更具體。例如。編寫DAO方法,這些方法只返回每個用例所需的對象的實例?可能是很多額外的方法... 3.從頭開始休眠並自己做? 4.不能真正想到其他解決方案。有什麼建議麼?

最佳做法是什麼?

回答

25
  • 除非確實需要,否則不要使用連接。他們不會允許您使用延遲加載,也不使用第二級緩存進行關聯
  • 對於大型集合使用lazy =「extra」,它不會檢索所有元素,除非您提出要求,還可以使用size ()方法,例如不從數據庫獲取元素
  • 如果可能的話,使用load()方法,因爲它只在需要時才發出select查詢。例如。如果你有一本書和作者,你想他們聯想到一起,這將不會發出任何選擇,只有一個INSERT語句:

    Book b = (Book) session.load(Book.class, bookId); 
    Author a = (Author) session.load(Author.class, authorId); 
    b.setAuthor(a); 
    session.save(b); 
    
  • 使用命名查詢(在您的HBM文件或在@NamedQuery中),以便在每個查詢期間不會分析它們。直到它的需要,不要使用標準的API(這使得不可能用在這種情況下的PreparedStatement緩存)

  • 使用OSIV在你的web應用程序,因爲它會加載數據,只有當/如果它需要
  • 使用只讀模式僅供選擇:session.setReadOnly(object, true)。這將使Hibernate不會在持久性上下文中保留所選實體的原始快照以進一步進行髒檢查。
  • 用戶二級緩存和查詢緩存,用於讀取大多數和只讀數據。
  • 使用FlushMode.COMMIT而不是AUTO,以便Hibernate在更新前不會發出select,但要準備好這可能會導致陳舊的數據被寫入(儘管樂觀鎖定可以幫助您)。
  • 看看批量抓取(批量大小),以便一次選擇多個實體/集合,而不是爲每個實體/集合發出單獨的查詢。
  • 查詢如'從實體中選擇新的實體(id,someField)'以僅檢索必需的字段。看看結果變形金剛。
  • 如果需要,使用批處理操作(如刪除)
  • 如果使用本機查詢,請明確指定哪些緩存區域應該失效(默認情況下爲全部)。
  • 查看樹狀結構的物化路徑和嵌套集。
  • 設置c3p0.max_statements爲了啓用池中的PreparedStatment緩存並啓用數據庫的語句緩存(如果默認情況下它被關閉)。
  • 使用StatelessSession,如果有可能,它克服髒檢查,級聯,攔截等
  • 不要使用含有加入到集合的查詢沿着分頁(setMaxResults()setFirstResult()),這將導致所有記錄從拉數據庫和分頁將在Hibernate的內存中發生。如果你想分頁,理想情況下你不應該使用連接。如果你不能逃避它,請使用批量抓取。

其實有很多技巧,但我現在還記不起來。

+0

OSIV你能解釋我沒有得到 – 2016-07-07 01:39:21

1

我相信你想檢討這個section in the Hibernate manual

我認爲你最初的問題是「...不合理的很多db-calls ...」是他們所謂的「N + 1選擇問題」的一個實例。如果是這樣,他們可以選擇如何處理它。

  1. 使獲取類型加入。然後,假設沒有中間集合,您將有多個連接的單個選擇。
  2. 做延遲加載。
  3. 也許有些人,例如我沒有經驗的FetchProfiles。

前兩個可以在關聯級別指定,並且可以在查詢級別覆蓋獲取類型。你應該能夠讓你的查詢只做你需要的東西,不要再用這些工具通過'好'的SQL查詢來做。

3

正如我在this article或我High-Performance JavaPersistence book解釋,有很多事情可以做,來加速性能的Hibernate,如:

  1. Enabling SQL statement logging,這樣就可以驗證所有語句,甚至detect N+1 query problems during testing
  2. 使用數據庫連接管理和監視使用FlexyPool
  3. JDBC batching可減少提交INSERT,UPDATE和DELETE語句所需的往返次數。
  4. JDBC Statement caching
  5. JPA標識符優化像pooled or pooled-lo
  6. 選擇緊湊列類型
  7. 使用權的關係:bidirectional @OneToMany instead of unidirectional one,使用@MapsId for @OneToOneusing Set for @ManyToMany
  8. 使用inheritance the right waypreferring SINGLE_TABLE for performance reasons
  9. Minding the Persistence Context size and avoiding long-running transactions
  10. 使用操作系統的緩存,在跳轉到二級緩存之前進行數據庫緩存通過SQL native queries做數據庫複製
  11. 釋放出的數據庫查詢功能,當H也是有用的卸載主節點
  12. 分割多間寫一到一個實體reduce optimistic locking false positives,並得到一個更好的機會,連打數據庫緩存修改某些實體時。