您好,登錄后才能下訂單哦!
本篇內容主要講解“Hibernate高級集合映射是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Hibernate高級集合映射是什么”吧!
Hibernate高級集合映射主要分為有序集合、雙向關聯、雙向關聯,涉及有序集合類、 三重關聯(Ternary associations)、使用<idbag>。
1. 有序集合(Sorted collections)
Hibernate高級集合映射支持實現java.util.SortedMap和java.util.SortedSet的集合。你必須在映射文件中指定一個比較器:
<set name="aliases" table="person_aliases" sort="natural"> <key column="person"/> <element column="name" type="string"/> </set> <map name="holidays" sort="my.custom.HolidayComparator"> <key column="year_id"/> <map-key column="hol_name" type="string"/> <element column="hol_date" type="date"/> </map>
sort屬性中允許的值包括unsorted,natural和某個實現了java.util.Comparator的類的名稱。
分類集合的行為事實上象java.util.TreeSet或者java.util.TreeMap。
如果你希望數據庫自己對集合元素排序,可以利用set,bag或者map映射中的order-by屬性。這個解決方案只能在jdk1.4或者更高的jdk版本中才可以實現(通過LinkedHashSet或者 LinkedHashMap實現)。 它是在SQL查詢中完成排序,而不是在內存中。
<set name="aliases" table="person_aliases" order-by="lower(name) asc"> <key column="person"/> <element column="name" type="string"/> </set> <map name="holidays" order-by="hol_date, hol_name"> <key column="year_id"/> <map-key column="hol_name" type="string"/> <element column="hol_date" type="date"/> </map>
注意: 這個order-by屬性的值是一個SQL排序子句而不是HQL的!
關聯還可以在運行時使用集合filter()根據任意的條件來排序。
ssortedUsers = s.createFilter( group.getUsers(), "order by this.name" ).list();
2. 雙向關聯(Bidirectional associations)
雙向關聯允許通過關聯的任一端訪問另外一端。在Hibernate中, 支持兩種類型的雙向關聯:
◆一對多(one-to-many)
Set或者bag值在一端, 單獨值(非集合)在另外一端
◆多對多(many-to-many)
兩端都是set或bag值
要建立一個雙向的多對多關聯,只需要映射兩個many-to-many關聯到同一個數據庫表中,并再定義其中的一端為inverse(使用哪一端要根據你的選擇,但它不能是一個索引集合)。
這里有一個many-to-many的雙向關聯的例子;每一個category都可以有很多items,每一個items可以屬于很多categories:
<class name="Category"> <id name="id" column="CATEGORY_ID"/> ... <bag name="items" table="CATEGORY_ITEM"> <key column="CATEGORY_ID"/> <many-to-many class="Item" column="ITEM_ID"/> </bag> </class> <class name="Item"> <id name="id" column="CATEGORY_ID"/> ... <!-- inverse end --> <bag name="categories" table="CATEGORY_ITEM" inverse="true"> <key column="ITEM_ID"/> <many-to-many class="Category" column="CATEGORY_ID"/> </bag> </class>
如果只對關聯的反向端進行了改變,這個改變不會被持久化。 這表示Hibernate為每個雙向關聯在內存中存在兩次表現,一個從A連接到B,另一個從B連接到A。如果你回想一下Java對象模型,我們是如何在Java中創建多對多關系的,這可以讓你更容易理解:
category.getItems().add(item); // The category now "knows" about the relationship item.getCategories().add(category); // The item now "knows" about the relationship session.persist(item); // The relationship won''t be saved! session.persist(category); // The relationship will be saved
非反向端用于把內存中的表示保存到數據庫中。
要建立一個一對多的雙向關聯,你可以通過把一個一對多關聯,作為一個多對一關聯映射到到同一張表的字段上,并且在"多"的那一端定義inverse="true"。
<class name="Parent"> <id name="id" column="parent_id"/> .... <set name="children" inverse="true"> <key column="parent_id"/> <one-to-many class="Child"/> </set> </class> <class name="Child"> <id name="id" column="child_id"/> .... <many-to-one name="parent" class="Parent" column="parent_id" not-null="true"/> </class>
在“一”這一端定義inverse="true"不會影響級聯操作,二者是正交的概念!
3. 雙向關聯,涉及有序集合類
對于有一端是<list>或者<map>的雙向關聯,需要加以特別考慮。假若子類中的一個屬性映射到索引字段,沒問題,我們仍然可以在集合類映射上使用inverse="true":
<class name="Parent"> <id name="id" column="parent_id"/> .... <map name="children" inverse="true"> <key column="parent_id"/> <map-key column="name" type="string"/> <one-to-many class="Child"/> </map> </class> <class name="Child"> <id name="id" column="child_id"/> .... <property name="name" not-null="true"/> <many-to-one name="parent" class="Parent" column="parent_id" not-null="true"/> </class>
但是,假若子類中沒有這樣的屬性存在,我們不能認為這個關聯是真正的雙向關聯(信息不對稱,在關聯的一端有一些另外一端沒有的信息)。在這種情況下,我們不能使用inverse="true"。我們需要這樣用:
<class name="Parent"> <id name="id" column="parent_id"/> .... <map name="children"> <key column="parent_id" not-null="true"/> <map-key column="name" type="string"/> <one-to-many class="Child"/> </map> </class> <class name="Child"> <id name="id" column="child_id"/> .... <many-to-one name="parent" class="Parent" column="parent_id" insert="false" update="false" not-null="true"/> </class>
注意在這個映射中,關聯中集合類"值"一端負責來更新外鍵.TODO: Does this really result in some unnecessary update statements?
4. 三重關聯(Ternary associations)
有三種可能的途徑來映射一個三重關聯。***種是使用一個Map,把一個關聯作為其索引:
<map name="contracts"> <key column="employer_id" not-null="true"/> <map-key-many-to-many column="employee_id" class="Employee"/> <one-to-many class="Contract"/> </map> <map name="connections"> <key column="incoming_node_id"/> <map-key-many-to-many column="outgoing_node_id" class="Node"/> <many-to-many column="connection_id" class="Connection"/> </map>
第二種方法是簡單的把關聯重新建模為一個實體類。這使我們最經常使用的方法。
***一種選擇是使用復合元素,我們會在后面討論
5. 使用<idbag>
如果你完全信奉我們對于“聯合主鍵(composite keys)是個壞東西”,和“實體應該使用(無機的)自己生成的代用標識符(surrogate keys)”的觀點,也許你會感到有一些奇怪,我們目前為止展示的多對多關聯和值集合都是映射成為帶有聯合主鍵的表的!現在,這一點非常值得爭辯;看上去一個單純的關聯表并不能從代用標識符中獲得什么好處(雖然使用組合值的集合可能會獲得一點好處)。不過,Hibernate提供了一個(一點點試驗性質的)功能,讓你把多對多關聯和值集合應得到一個使用代用標識符的表去。
<idbag> 屬性讓你使用bag語義來映射一個List (或Collection)。
<idbag name="lovers" table="LOVERS"> <collection-id column="ID" type="long"> <generator class="sequence"/> </collection-id> <key column="PERSON1"/> <many-to-many column="PERSON2" class="Person" fetch="join"/> </idbag>
你可以理解,<idbag>人工的id生成器,就好像是實體類一樣!集合的每一行都有一個不同的人造關鍵字。但是,Hibernate沒有提供任何機制來讓你取得某個特定行的人造關鍵字。
注意<idbag>的更新性能要比普通的<bag>高得多!Hibernate可以有效的定位到不同的行,分別進行更新或刪除工作,就如同處理一個list, map或者set一樣。
在目前的實現中,還不支持使用identity標識符生成器策略來生成<idbag>集合的標識符。
到此,相信大家對“Hibernate高級集合映射是什么”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。