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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

hibernate 映射_Hibernate映射集合性能问题

發布時間:2023/12/3 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 hibernate 映射_Hibernate映射集合性能问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

hibernate 映射

首先,本文的靈感來自于Burt Beckwith在2011年1月27日于SpringOne 2GX上發表的有關高級GORM –性能,自定義和監視的演講 。 簡而言之, Burt Beckwith討論了使用映射集合和GORM中的Hibernate 2級緩存的潛在性能問題,以及避免此類性能下降的策略。

盡管如此, Burt Beckwith在演講中指出的有關映射集合的性能問題通常適用于每個啟用Hibernate的應用程序。 這就是為什么看完他的演講后我才意識到他的提議正是我自己一直在做的事情,并指示我的同事在使用Hibernate中的 映射集合進行開發時應該做。

以下是使用Hibernate 映射集合時要考慮的5件事:

讓我們考慮以下經典的“圖書館–訪問”示例:

以下Library類具有Visit實例的集合:

package eg; import java.util.Set;public class Library {private long id;private Set visits;public long getId() { return id; }private void setId(long id) { this.id=id; }private Set getVisits() { return visits; }private void setVisits(Set visits) { this.visits=visits; }........ }

以下是Visit類:

package eg; import java.util.Set;public class Visit {private long id;private String personName;public long getId() { return id; }private void setId(long id) { this.id=id; }private String getPersonName() { return personName; }private void setPersonName(String personName) { this.personName=personName; }........ }

假設一個庫具有多次唯一訪問,并且每次訪問都與一個不同的庫相關聯,則可以使用如下所示的單向 一對多關聯:

<hibernate-mapping><class name="Library"><id name="id"><generator class="sequence"/></id><set name="visits"><key column="library_id" not-null="true"/><one-to-many class="Visit"/></set></class><class name="Visit"><id name="id"><generator class="sequence"/></id><property name="personName"/></class></hibernate-mapping>

我還將提供上述模式的表定義示例:

create table library (id bigint not null primary key ) create table visit(id bigint not nullprimary key,personName varchar(255),library_id bigint not null) alter table visit add constraint visitfk0 (library_id) references library

那么這張照片怎么了?

當您嘗試添加到映射的集合時,可能會出現性能瓶頸。 如您所見,該集合被實現為Set 。 集合保證其所包含元素之間的唯一性。 那么, Hibernate如何知道一個新項目是唯一的以便將其添加到Set中呢? 好吧,不要驚訝; 添加到Set中需要從數據庫加載所有可用項。 Hibernate將每一項與新的進行比較,以確保唯一性。 此外,以上是我們無法繞過的標準行為,即使我們由于業務規則而知道新項目是唯一的!

在我們的映射集合中使用List實現也無法解決向其添加項目時的性能瓶頸問題。 盡管列表不保證唯一性,但它們可以保證項目的順序。 因此,為了在映射的List中保持正確的項目順序,即使我們將其添加到列表的末尾, Hibernate也必須提取整個集合。

我認為,添加一個新的“ 訪問 圖書館”的路很長,您不同意嗎?

此外,上面的示例在開發中非常有效,因為我們只有幾次訪問。 在每個庫可能有數百萬次訪問的生產環境中,請想象一下,當您嘗試增加一個庫時會降低性能!

為了克服上述性能問題,我們可以將集合映射為Bag ,這只是一個常規集合,沒有順序或唯一性保證,但是在這樣做之前,請考慮以下我的最后一點。

當您從集合中刪除對象或向集合中添加對象時,集合所有者的版本號會增加。 因此,當同時進行訪問創建時,在Library對象上存在人為的樂觀鎖定異常的高風險。 我們將樂觀的鎖定異常描述為“人造的”,因為它們發生在集合所有者對象( Library )上,當我們從Visits集合中添加/刪除項目時,我們不覺得我們正在編輯(但是我們正在!)。

我要指出的是,相同的規則適用于多對多關聯類型。

那么解決方案是什么?

解決方案很簡單,從所有者( Library )對象中刪除映射的集合 ,然后“手動”執行Visit項目的插入和刪除。 提議的解決方案通過以下方式影響使用:

  • 要將訪問添加到庫,我們必須創建一個新的“ 訪問”項,將其與“ 庫”項相關聯,并將其顯式保存在數據庫中。
  • 要從圖書館中刪除訪問 ,我們必須搜索“訪問”表,找到我們需要的確切記錄并將其刪除。
  • 使用建議的解決方案,不支持級聯。 要刪除資料庫,您需要先刪除(取消關聯)其所有訪問記錄。
  • 為了保持環境整潔有序,您可以通過實現一個助手方法將“訪問”偽集合恢復到Library對象,該方法將查詢數據庫并返回與特定Library相關的所有Visit對象。 此外,您可以在Visit項目中實現幾個幫助程序方法,這些方法將執行實際的訪問記錄插入和刪除操作。

    下面,我們提供Library類, Visit類和Hibernate映射的更新版本,以便符合我們提出的解決方案:

    首先更新的類:

    package eg; import java.util.Set;public class Library {private long id;public long getId() { return id; }private void setId(long id) { this.id=id; }public Set getVisits() { // TODO : return select * from visit where visit.library_id=this.id}........ }

    如您所見,我們刪除了映射的集合,并引入了方法“ getVisits() ”,該方法應用于返回特定Library實例的所有Visit項目(TODO注釋為偽代碼)。

    以下是更新的Visit類:

    package eg; import java.util.Set;public class Visit {private long id;private String personName;private long library_id;public long getId() { return id; }private void setId(long id) { this.id=id; }private String getPersonName() { return personName; }private void setPersonName(String personName) { this.personName=personName; }private long getLibrary_id() { return library_id; }private void setLibrary_id(long library_id) { this. library_id =library_id; }........ }

    如您所見,我們已經在Visit對象中添加了“ library_id ”字段,以便能夠將其與Library項目相關聯。

    最后是更新的Hibernate映射:

    <hibernate-mapping><class name="Library"><id name="id"><generator class="sequence"/></id></class><class name="Visit"><id name="id"><generator class="sequence"/></id><property name="personName"/><property name="library_id"/></class></hibernate-mapping>

    因此,永遠不要在Hibernate中使用映射的集合嗎?

    好吧,說實話,不。您需要檢查每個案例,以便決定要做什么。 如果收集的數量較小,則標準方法很好-在多對多關聯方案的情況下,雙方都是如此。 此外,集合將包含代理,因此在初始化之前,它們將小于實際實例。

    編碼愉快! 別忘了分享!

    賈斯汀

    聚苯乙烯

    在TheServerSide上對這篇文章進行了相當長的辯論之后,一個或我們的讀者Eb Bras提供了Hibernate的“技巧和竅門”的有用列表,讓他看看該說些什么:

    這是我長期記錄的一些Hibernate提示和技巧:

    反=“真”
    一對多的父子關聯中(與另一個實體或用作實體的值類型)盡可能多地使用它。
    該屬性在集合標簽(如“ set”)上設置,表示多對一擁有關聯,并負責所有數據庫的插入/更新/刪除。 它使關聯成為孩子的一部分。 它將保存外鍵的數據庫更新,因為它將在插入子代時直接發生。

    尤其是在使用“集合”作為映射類型時,它可以提高性能,因為不需要將子級添加到父級集合中,這樣可以節省整個集合的負載。 那就是:由于集合映射的性質,添加新子元素時必須始終加載整個集合,因為這是hibernate可以確保新條目不是重復項的唯一方法,這是JRE Set的功能接口。
    如果它涉及一個組件集合(=僅包含純值類型的集合),則inverse = true會被忽略并且沒有意義,因為Hibernate對對象具有完全控制權,并將選擇執行其操作的最佳方法。
    如果涉及分離的DTO對象(不包含任何Hibernate對象),則Hibernate將刪除所有值類型子對象,然后插入它們,因為它不知道哪個對象是新對象或存在對象,因為它已完全分離。 Hibernate將其視為新集合。

    懶惰的Set.getChilds()是邪惡的
    使用getChilds()會返回一個Set并會延遲加載所有子項,請務必小心。
    當您只想添加或刪除孩子時,請勿使用此功能

    始終實現equals / hashcode
    確保始終對Hibernate管理的每個對象實施equals / hashcode,即使它看起來并不重要。 對于值類型對象也是如此。
    如果對象不包含作為equals / hashcode候選者的屬性,請使用代理密鑰,例如,由UUID組成。 Hibernate使用equals / hashcode找出數據庫中是否已經存在對象。 如果它涉及到一個現有對象,但Hibernate認為它是一個新對象,因為equals / hashcode沒有正確實現,則Hibernate將執行插入操作,并可能刪除舊值。 特別是對于Set中的值類型而言,這一點很重要,必須進行測試,因為它可以節省數據庫流量。 想法:您正在給Hibernate提供更多的知識,以便它可以用來優化他的動作。

    使用版本
    始終將version屬性與實體或用作實體的值類型一起使用。
    由于Hibernate使用此信息來發現它是否涉及新對象或現有對象,因此這將減少數據庫流量。 如果不存在此屬性,則必須命中數據庫以查找是否涉及新對象或現有對象。

    渴望獲取
    默認情況下,非延遲集合(子項)是通過額外選擇查詢加載的,該查詢僅在從數據庫加載父項之后才執行。
    通過啟用熱切獲取,可以通過加載集合映射標簽上的屬性“ fetch = join”來完成與加載父項相同的查詢。 如果啟用,則通過左外部聯接加載子項。 測試這是否可以提高性能。 如果發生許多聯接,或者如果它涉及具有許多列的表,則性能將變差而不是變好。

    在值類型子對象中使用代理鍵
    Hibernate將在由所有非空列組成的父子關系的值類型子項中構造主鍵。 這可能會導致奇怪的主鍵組合,尤其是在涉及日期列時。 日期列不應該是主鍵的一部分,因為它的毫秒部分將導致幾乎絕不相同的主鍵。 這將導致奇怪的數據庫性能,并且可能導致性能下降。
    為了改善這一點,我們在所有子值類型對象中使用代理鍵,這是唯一的非null屬性。 然后,Hibernate將構造一個由外鍵和代理鍵組成的主鍵,該主鍵是邏輯上的且性能良好。 請注意,代理鍵僅用于數據庫優化,并且不需要在可能包含業務邏輯的equals / hashcode中使用。

    相關文章 :
    • Java最佳實踐–高性能序列化
    • Java最佳實踐– Vector vs ArrayList vs HashSet
    • Java最佳實踐–字符串性能和精確字符串匹配
    • Java最佳實踐–隊列之戰和鏈接的ConcurrentHashMap
    • Java最佳實踐– Char到Byte和Byte到Char的轉換
    • 如何在不到1ms的延遲內完成100K TPS
    • 提升您的Hibernate引擎
    • Cajo,用Java完成分布式計算的最簡單方法

    翻譯自: https://www.javacodegeeks.com/2011/02/hibernate-mapped-collections.html

    hibernate 映射

    總結

    以上是生活随笔為你收集整理的hibernate 映射_Hibernate映射集合性能问题的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。