日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

避免延迟的JPA集合

發(fā)布時間:2023/12/3 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 避免延迟的JPA集合 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
Hibernate(實際上是JPA)具有集合映射:@ OneToMany,@ ManyToMany,@ ElementCollection。 所有這些默認(rèn)情況下都是惰性的。 這意味著集合是List或Set接口的特定實現(xiàn),其中包含對持久會話的引用,并且只有在訪問集合時才從數(shù)據(jù)庫中加載值。 如果您僅偶爾使用集合,則可以節(jié)省不必要的數(shù)據(jù)庫查詢。

但是,這有一個問題。 在我看來,異常是第二個最常見的異常(在NullPointerException之后),即LazyInitializationException。 問題在于會話通常為您的服務(wù)層打開,并且在您將實體返回到視圖層后立即關(guān)閉。 當(dāng)您嘗試在視圖中迭代未初始化的集合時(例如jsp),該集合將引發(fā)LazyInitializationException,因為它們所擁有的引用所在的會話已經(jīng)關(guān)閉,并且無法獲取這些項。

如何解決? 所謂的OpenSessionInView / OpenEntityManagerInView“模式”。 簡而言之:您可以創(chuàng)建一個過濾器,以在請求啟動時打開會話,并在呈現(xiàn)視圖后(而不是在服務(wù)層完成后)關(guān)閉會話。 有人稱其為反模式,因為它將持久性處理泄漏到視圖層,并使設(shè)置復(fù)雜化。 我不會說那么糟糕:通常,它可以解決問題而不引入其他問題。 但是在我參與的所有最新項目中,我們沒有使用OpenSessionInView,而且效果很好。

之所以能正常工作,是因為我們沒有使用惰性集合。 但是,您會正確地指出,當(dāng)您加載單個實體時,您將獲取“整個世界”。 好吧,不。 * ToMany映射有兩種類型:

  • 值類型映射,集合在邏輯上不包含十幾個元素。 在大多數(shù)情況下,這是@ElementCollection,還有@ * ToMany,它們帶有諸如“ Category”或“ Price”之類的項,它們只是更復(fù)雜的值對象,但自身不包含任何其他映射。 這些類型的集合的另一個共同特征是它們通常與它們自己的實體一起顯示在UI中。 例如,您最有可能要顯示文章的類別。 對于這種類型的集合,EAGER是更好的選擇。 無論如何,您都必須獲取它們,為什么不讓休眠(或任何jpa實現(xiàn))想到一些巧妙的連接呢? 就像我說的那樣-邏輯上集合不超過一打或十二個,因此獲取它們不會對性能造成影響。 而且,從邏輯上講,它們不會與它們一起獲取大對象圖。
  • 大型核心實體之間的映射。 可以是“用戶所下的所有訂單”或“組織中的所有用戶”,“供應(yīng)商的所有項目”等。您當(dāng)然不想急于獲取它們。 因為如果您為一個組織獲取2000個用戶,那么每個組織又有1000個訂單,而一個訂單平均有3個項目,這反過來又包含所有購買該項目的人的集合。.您將最終擁有整個數(shù)據(jù)庫在記憶中。 顯然您需要惰性集合,對嗎? 好吧,不。 在這種情況下,您根本不應(yīng)該使用集合映射。 在99%的情況下,這些類型的關(guān)系顯示在UI的頁面列表中。 或在搜索結(jié)果中。 它們永遠(yuǎn)不會(也永遠(yuǎn)不會)全部顯示在一個屏幕上(或者,如果您的應(yīng)用程序提供了類似REST API之類的東西,則很少應(yīng)該在一個API調(diào)用中返回它們)。 您必須對其進(jìn)行查詢,并使用query.setMaxResults和query.setFirstResult()(或使用一些限制性條件來限制它們)。 此外,對集合進(jìn)行映射意味著有人會在某個時候嘗試使用它們,這可能會失敗。 并且如果對象已序列化(xml,json等),則將獲取集合內(nèi)容。 您幾乎肯定不想發(fā)生的事情。 (這里的想法草案:JPA可以有一個PagedList集合,該集合將允許分頁的延遲提取,從而消除了查詢的需要)

所以我剛才說的是-永遠(yuǎn)不要使用惰性集合。 將eager集合用于非常簡單的淺表映射,將分頁查詢用于較大的映射。

好吧,不完全是。 延遲集合在那里并且它們有應(yīng)用,盡管它是相當(dāng)有限的。 或者,至少它們比所使用的方法不太適用。 這是我發(fā)現(xiàn)適用的示例場景。 在我的附帶項目中,我有一個Message實體,并且它包含一個Picture實體的集合。 用戶上載圖片時,它將存儲在該集合中。 一條消息最多可以包含10張圖片,因此非常希望收藏。 但是,然后,Message是最常用的實體–實際上是在每個請求中獲取的。 但是只有一些消息帶有圖片(您的信息流中有多少條推文有圖片上傳?)。 因此,我不想讓休眠狀態(tài)進(jìn)行查詢只是為了查找給定消息沒有圖片。 因此,我將圖片數(shù)量存儲在一個單獨的字段中,使圖片集合變得懶惰,并且僅在圖片數(shù)量> 0時才手動對其進(jìn)行Hibernate.initialize(..)。

因此,在某些情況下,當(dāng)實體具有屬于上述第一類的可選集合時(“小型淺表集合”)。 因此,如果它很小,很淺并且是可選的(例如,在不到20%的情況下使用),則應(yīng)該使用Lazy來保存不必要的查詢。

其他方面–懶惰的收藏會讓您的生活更艱難。

參考:在Bozho的技術(shù)博客上, 避免與我們的JCG合作伙伴 Bozho一起使用懶惰的JPA Collections 。

相關(guān)文章 :

  • 休眠陷阱
  • DataNucleus 3.0與Hibernate 3.5
  • Hibernate映射集合性能問題
  • ORM問題
  • 框架使開發(fā)人員愚蠢嗎?
  • 每個程序員都應(yīng)該知道的事情
  • Java最佳實踐

翻譯自: https://www.javacodegeeks.com/2011/10/avoid-lazy-jpa-collections.html

總結(jié)

以上是生活随笔為你收集整理的避免延迟的JPA集合的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。