自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

解讀Hibernate高級(jí)集合映射

開發(fā) 后端
Hibernate高級(jí)集合映射(Advanced collection mappings),Hibernate高級(jí)集合映射主要分為有序集合、雙向關(guān)聯(lián)、雙向關(guān)聯(lián),涉及有序集合類、 三重關(guān)聯(lián)(Ternary associations)、使用<idbag>。

本文主要介紹Hibernate高級(jí)集合映射(Advanced collection mappings),Hibernate高級(jí)集合映射主要分為有序集合、雙向關(guān)聯(lián)、雙向關(guān)聯(lián),涉及有序集合類、 三重關(guān)聯(lián)(Ternary associations)、使用<idbag>。

1. 有序集合(Sorted collections)

Hibernate高級(jí)集合映射支持實(shí)現(xiàn)java.util.SortedMap和java.util.SortedSet的集合。你必須在映射文件中指定一個(gè)比較器:

  1. <set name="aliases"   
  2.             table="person_aliases"   
  3.             sort="natural"> 
  4.     <key column="person"/> 
  5.     <element column="name" type="string"/> 
  6. </set> 
  7.  
  8. <map name="holidays" sort="my.custom.HolidayComparator"> 
  9.     <key column="year_id"/> 
  10.     <map-key column="hol_name" type="string"/> 
  11.     <element column="hol_date" type="date"/> 
  12. </map> 

sort屬性中允許的值包括unsorted,natural和某個(gè)實(shí)現(xiàn)了java.util.Comparator的類的名稱。

分類集合的行為事實(shí)上象java.util.TreeSet或者java.util.TreeMap。

如果你希望數(shù)據(jù)庫(kù)自己對(duì)集合元素排序,可以利用set,bag或者map映射中的order-by屬性。這個(gè)解決方案只能在jdk1.4或者更高的jdk版本中才可以實(shí)現(xiàn)(通過LinkedHashSet或者 LinkedHashMap實(shí)現(xiàn))。 它是在SQL查詢中完成排序,而不是在內(nèi)存中。

  1. <set name="aliases" table="person_aliases" order-by="lower(name) asc"> 
  2.     <key column="person"/> 
  3.     <element column="name" type="string"/> 
  4. </set> 
  5.  
  6. <map name="holidays" order-by="hol_date, hol_name"> 
  7.     <key column="year_id"/> 
  8.     <map-key column="hol_name" type="string"/> 
  9.     <element column="hol_date" type="date"/> 
  10. </map> 

注意: 這個(gè)order-by屬性的值是一個(gè)SQL排序子句而不是HQL的!

關(guān)聯(lián)還可以在運(yùn)行時(shí)使用集合filter()根據(jù)任意的條件來排序。

  1. ssortedUsers = s.createFilter( group.getUsers(), "order by this.name" ).list(); 

2. 雙向關(guān)聯(lián)(Bidirectional associations)

雙向關(guān)聯(lián)允許通過關(guān)聯(lián)的任一端訪問另外一端。在Hibernate中, 支持兩種類型的雙向關(guān)聯(lián):

◆一對(duì)多(one-to-many)
Set或者bag值在一端, 單獨(dú)值(非集合)在另外一端

◆多對(duì)多(many-to-many)
兩端都是set或bag值


要建立一個(gè)雙向的多對(duì)多關(guān)聯(lián),只需要映射兩個(gè)many-to-many關(guān)聯(lián)到同一個(gè)數(shù)據(jù)庫(kù)表中,并再定義其中的一端為inverse(使用哪一端要根據(jù)你的選擇,但它不能是一個(gè)索引集合)。

這里有一個(gè)many-to-many的雙向關(guān)聯(lián)的例子;每一個(gè)category都可以有很多items,每一個(gè)items可以屬于很多categories:

  1. <class name="Category"> 
  2.     <id name="id" column="CATEGORY_ID"/> 
  3.     ...  
  4.     <bag name="items" table="CATEGORY_ITEM"> 
  5.         <key column="CATEGORY_ID"/> 
  6.         <many-to-many class="Item" column="ITEM_ID"/> 
  7.     </bag> 
  8. </class> 
  9.  
  10. <class name="Item"> 
  11.     <id name="id" column="CATEGORY_ID"/> 
  12.     ...  
  13.  
  14.     <!-- inverse end --> 
  15.     <bag name="categories" table="CATEGORY_ITEM" inverse="true"> 
  16.         <key column="ITEM_ID"/> 
  17.         <many-to-many class="Category" column="CATEGORY_ID"/> 
  18.     </bag> 
  19. </class> 

如果只對(duì)關(guān)聯(lián)的反向端進(jìn)行了改變,這個(gè)改變不會(huì)被持久化。 這表示Hibernate為每個(gè)雙向關(guān)聯(lián)在內(nèi)存中存在兩次表現(xiàn),一個(gè)從A連接到B,另一個(gè)從B連接到A。如果你回想一下Java對(duì)象模型,我們是如何在Java中創(chuàng)建多對(duì)多關(guān)系的,這可以讓你更容易理解:

  1. category.getItems().add(item);          // The category now "knows" about the relationship  
  2. item.getCategories().add(category);     // The item now "knows" about the relationship  
  3.  
  4. session.persist(item);                   // The relationship won''t be saved!  
  5. session.persist(category);               // The relationship will be saved 

非反向端用于把內(nèi)存中的表示保存到數(shù)據(jù)庫(kù)中。

要建立一個(gè)一對(duì)多的雙向關(guān)聯(lián),你可以通過把一個(gè)一對(duì)多關(guān)聯(lián),作為一個(gè)多對(duì)一關(guān)聯(lián)映射到到同一張表的字段上,并且在"多"的那一端定義inverse="true"。

  1. <class name="Parent"> 
  2.     <id name="id" column="parent_id"/> 
  3.     ....  
  4.     <set name="children" inverse="true"> 
  5.         <key column="parent_id"/> 
  6.         <one-to-many class="Child"/> 
  7.     </set> 
  8. </class> 
  9.  
  10. <class name="Child"> 
  11.     <id name="id" column="child_id"/> 
  12.     ....  
  13.     <many-to-one name="parent"   
  14.         class="Parent"   
  15.         column="parent_id" 
  16.         not-null="true"/> 
  17. </class> 

在“一”這一端定義inverse="true"不會(huì)影響級(jí)聯(lián)操作,二者是正交的概念!

3. 雙向關(guān)聯(lián),涉及有序集合類

對(duì)于有一端是<list>或者<map>的雙向關(guān)聯(lián),需要加以特別考慮。假若子類中的一個(gè)屬性映射到索引字段,沒問題,我們?nèi)匀豢梢栽诩项愑成渖鲜褂胕nverse="true":

  1. <class name="Parent"> 
  2.     <id name="id" column="parent_id"/> 
  3.     ....  
  4.     <map name="children" inverse="true"> 
  5.         <key column="parent_id"/> 
  6.         <map-key column="name"   
  7.             type="string"/> 
  8.         <one-to-many class="Child"/> 
  9.     </map> 
  10. </class> 
  11.  
  12. <class name="Child"> 
  13.     <id name="id" column="child_id"/> 
  14.     ....  
  15.     <property name="name"   
  16.         not-null="true"/> 
  17.     <many-to-one name="parent"   
  18.         class="Parent"   
  19.         column="parent_id" 
  20.         not-null="true"/> 
  21. </class> 

但是,假若子類中沒有這樣的屬性存在,我們不能認(rèn)為這個(gè)關(guān)聯(lián)是真正的雙向關(guān)聯(lián)(信息不對(duì)稱,在關(guān)聯(lián)的一端有一些另外一端沒有的信息)。在這種情況下,我們不能使用inverse="true"。我們需要這樣用:

  1. <class name="Parent"> 
  2.     <id name="id" column="parent_id"/> 
  3.     ....  
  4.     <map name="children"> 
  5.         <key column="parent_id" 
  6.             not-null="true"/> 
  7.         <map-key column="name"   
  8.             type="string"/> 
  9.         <one-to-many class="Child"/> 
  10.     </map> 
  11. </class> 
  12.  
  13. <class name="Child"> 
  14.     <id name="id" column="child_id"/> 
  15.     ....  
  16.     <many-to-one name="parent"   
  17.         class="Parent"   
  18.         column="parent_id" 
  19.         insert="false" 
  20.         update="false" 
  21.         not-null="true"/> 
  22. </class> 

注意在這個(gè)映射中,關(guān)聯(lián)中集合類"值"一端負(fù)責(zé)來更新外鍵.TODO: Does this really result in some unnecessary update statements?

4. 三重關(guān)聯(lián)(Ternary associations)

有三種可能的途徑來映射一個(gè)三重關(guān)聯(lián)。***種是使用一個(gè)Map,把一個(gè)關(guān)聯(lián)作為其索引:

  1. <map name="contracts"> 
  2.     <key column="employer_id" not-null="true"/> 
  3.     <map-key-many-to-many column="employee_id" class="Employee"/> 
  4.     <one-to-many class="Contract"/> 
  5. </map> 
  6. <map name="connections"> 
  7.     <key column="incoming_node_id"/> 
  8.     <map-key-many-to-many column="outgoing_node_id" class="Node"/> 
  9.     <many-to-many column="connection_id" class="Connection"/> 
  10. </map> 

第二種方法是簡(jiǎn)單的把關(guān)聯(lián)重新建模為一個(gè)實(shí)體類。這使我們最經(jīng)常使用的方法。

***一種選擇是使用復(fù)合元素,我們會(huì)在后面討論

5. 使用<idbag>

如果你完全信奉我們對(duì)于“聯(lián)合主鍵(composite keys)是個(gè)壞東西”,和“實(shí)體應(yīng)該使用(無機(jī)的)自己生成的代用標(biāo)識(shí)符(surrogate keys)”的觀點(diǎn),也許你會(huì)感到有一些奇怪,我們目前為止展示的多對(duì)多關(guān)聯(lián)和值集合都是映射成為帶有聯(lián)合主鍵的表的!現(xiàn)在,這一點(diǎn)非常值得爭(zhēng)辯;看上去一個(gè)單純的關(guān)聯(lián)表并不能從代用標(biāo)識(shí)符中獲得什么好處(雖然使用組合值的集合可能會(huì)獲得一點(diǎn)好處)。不過,Hibernate提供了一個(gè)(一點(diǎn)點(diǎn)試驗(yàn)性質(zhì)的)功能,讓你把多對(duì)多關(guān)聯(lián)和值集合應(yīng)得到一個(gè)使用代用標(biāo)識(shí)符的表去。

<idbag> 屬性讓你使用bag語義來映射一個(gè)List (或Collection)。

  1. <idbag name="lovers" table="LOVERS"> 
  2.     <collection-id column="ID" type="long"> 
  3.         <generator class="sequence"/> 
  4.     </collection-id> 
  5.     <key column="PERSON1"/> 
  6.     <many-to-many column="PERSON2" class="Person" fetch="join"/> 
  7. </idbag> 

你可以理解,<idbag>人工的id生成器,就好像是實(shí)體類一樣!集合的每一行都有一個(gè)不同的人造關(guān)鍵字。但是,Hibernate沒有提供任何機(jī)制來讓你取得某個(gè)特定行的人造關(guān)鍵字。

注意<idbag>的更新性能要比普通的<bag>高得多!Hibernate可以有效的定位到不同的行,分別進(jìn)行更新或刪除工作,就如同處理一個(gè)list, map或者set一樣。

在目前的實(shí)現(xiàn)中,還不支持使用identity標(biāo)識(shí)符生成器策略來生成<idbag>集合的標(biāo)識(shí)符。

【編輯推薦】

  1. Hibernate樂觀并發(fā)控制
  2. Hibernate傳播性持久化攻略
  3. 深入了解Hibernate自動(dòng)狀態(tài)檢測(cè)
  4. 簡(jiǎn)單學(xué)會(huì)Hibernate對(duì)象持久化
  5. 分析Hibernate自增主鍵
責(zé)任編輯:仲衡 來源: javanb
相關(guān)推薦

2012-02-03 11:17:33

HibernateJava

2009-09-25 14:20:28

Hibernate繼承映射

2009-09-23 08:56:18

Hibernate cHibernate i

2012-02-02 16:13:29

HibernateJava

2009-09-23 17:34:18

Hibernate映射

2009-09-25 10:00:47

Hibernate映射

2012-02-03 10:07:04

HibernateJava

2009-09-22 15:10:22

Hibernate映射

2012-02-03 11:31:33

HibernateJava

2009-06-02 14:46:26

Hibernate關(guān)系映射教程

2009-09-25 12:59:52

Hibernate映射

2009-09-29 15:58:22

Hibernate映射

2009-09-27 10:02:29

定制Hibernate

2009-09-28 14:54:33

Hibernate映射

2009-09-25 12:31:13

Hibernate映射

2009-09-23 13:26:10

Hibernate對(duì)象

2012-02-08 12:17:38

HibernateJava

2012-03-19 16:27:05

JavaHibernate

2009-09-23 13:21:32

Hibernate O

2009-06-16 14:36:54

Hibernate繼承
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)