避免延迟的JPA集合
但是,這有一個問題。 在我看來,異常是第二個最常見的異常(在NullPointerException之后),即LazyInitializationException。 問題在于會話通常為您的服務(wù)層打開,并且在您將實(shí)體返回到視圖層后立即關(guān)閉。 當(dāng)您嘗試在視圖中迭代未初始化的集合時(例如jsp),該集合將引發(fā)LazyInitializationException,因?yàn)樗鼈兯鶕碛械囊盟诘臅捯呀?jīng)關(guān)閉,并且無法獲取這些項(xiàng)。
如何解決? 所謂的OpenSessionInView / OpenEntityManagerInView“模式”。 簡而言之:您可以創(chuàng)建一個過濾器,以在請求啟動時打開會話,并在呈現(xiàn)視圖后(而不是在服務(wù)層完成后)關(guān)閉會話。 有人稱其為反模式,因?yàn)樗鼘⒊志眯蕴幚硇孤┑揭晥D層,并使設(shè)置復(fù)雜化。 我不會說那么糟糕:通常,它可以解決問題而不引入其他問題。 但是在我參與的所有最新項(xiàng)目中,我們沒有使用OpenSessionInView,而且效果很好。
之所以能正常工作,是因?yàn)槲覀儧]有使用惰性集合。 但是,您會正確地指出,當(dāng)您加載單個實(shí)體時,您將獲取“整個世界”。 好吧,不。 * ToMany映射有兩種類型:
- 值類型映射,集合在邏輯上不包含十幾個元素。 在大多數(shù)情況下,這是@ElementCollection,還有@ * ToMany,它們帶有諸如“ Category”或“ Price”之類的項(xiàng),它們只是更復(fù)雜的值對象,但自身不包含任何其他映射。 這些類型的集合的另一個共同特征是它們通常與它們自己的實(shí)體一起顯示在UI中。 例如,您最有可能要顯示文章的類別。 對于這種類型的集合,EAGER是更好的選擇。 無論如何,您都必須獲取它們,為什么不讓休眠(或任何jpa實(shí)現(xiàn))想到一些巧妙的連接呢? 就像我說的那樣-邏輯上集合不超過一打或十二個,因此獲取它們不會對性能造成影響。 而且,從邏輯上講,它們不會與它們一起獲取大對象圖。
 - 大型核心實(shí)體之間的映射。 可以是“用戶所下的所有訂單”或“組織中的所有用戶”,“供應(yīng)商的所有項(xiàng)目”等。您當(dāng)然不想急于獲取它們。 因?yàn)槿绻鸀橐粋€組織獲取2000個用戶,那么每個組織又有1000個訂單,而一個訂單平均有3個項(xiàng)目,這反過來又包含所有購買該項(xiàng)目的人的集合。.您將最終擁有整個數(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)適用的示例場景。 在我的附帶項(xiàng)目中,我有一個Message實(shí)體,并且它包含一個Picture實(shí)體的集合。 用戶上載圖片時,它將存儲在該集合中。 一條消息最多可以包含10張圖片,因此非常希望收藏。 但是,然后,Message是最常用的實(shí)體–實(shí)際上是在每個請求中獲取的。 但是只有一些消息帶有圖片(您的信息流中有多少條推文有圖片上傳?)。 因此,我不想讓休眠狀態(tài)進(jìn)行查詢只是為了查找給定消息沒有圖片。 因此,我將圖片數(shù)量存儲在一個單獨(dú)的字段中,使圖片集合變得懶惰,并且僅在圖片數(shù)量> 0時才手動對其進(jìn)行Hibernate.initialize(..)。
因此,在某些情況下,當(dāng)實(shí)體具有屬于上述第一類的可選集合時(“小型淺表集合”)。 因此,如果它很小,很淺并且是可選的(例如,在不到20%的情況下使用),則應(yīng)該使用Lazy來保存不必要的查詢。
其他方面–懶惰的收藏會讓您的生活更艱難。
參考:在Bozho的技術(shù)博客上, 避免與我們的JCG合作伙伴 Bozho一起使用懶惰的JPA Collections 。
相關(guān)文章 :
- 休眠陷阱
 - DataNucleus 3.0與Hibernate 3.5
 - Hibernate映射集合性能問題
 - ORM問題
 - 框架使開發(fā)人員愚蠢嗎?
 - 每個程序員都應(yīng)該知道的事情
 - Java最佳實(shí)踐
 
翻譯自: https://www.javacodegeeks.com/2011/10/avoid-lazy-jpa-collections.html
總結(jié)
以上是生活随笔為你收集整理的避免延迟的JPA集合的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: 编程到底怎么学如何学电脑编程
 - 下一篇: 怎么开机用u盘重装系统如何用u盘给电脑重