【永恒的瞬間】
          ?Give me hapy ?

           

           

          (譯者注:在閱讀本章的時候,以后整個手冊的閱讀過程中,我們都會面臨一個名詞方面的問題,那就是“集合”。"Collections"和"Set"在中文里對應(yīng)都被翻譯為“集合”,但是他們的含義很不一樣。Collections是一個超集,Set是其中的一種。大部分情況下,本譯稿中泛指的未加英文注明的“集合”,都應(yīng)當(dāng)理解為“Collections”。在有些二者同時出現(xiàn),可能造成混淆的地方,我們用“集合類”來特指“Collecions”,“集合(Set)”來指"Set",一般都會在后面的括號中給出英文。希望大家在閱讀時聯(lián)系上下文理解,不要造成誤解。 與此同時,“元素”一詞對應(yīng)的英文“element”,也有兩個不同的含義。其一為集合的元素,是內(nèi)存中的一個變量;另一含義則是XML文檔中的一個標(biāo)簽所代表的元素。也請注意區(qū)別。 本章中,特別是后半部分是需要反復(fù)閱讀才能理解清楚的。如果遇到任何疑問,請記住,英文版本的reference是惟一標(biāo)準(zhǔn)的參考資料。)

          Hibernate要求持久化集合值字段必須聲明為接口,比如:

          public class Product {
          private String serialNumber;
          private Set parts = new HashSet();
          public Set getParts() { return parts; }
          void setParts(Set parts) { this.parts = parts; }
          public String getSerialNumber() { return serialNumber; }
          void setSerialNumber(String sn) { serialNumber = sn; }
          }

          實際的接口可能是java.util.Set, java.util.Collection, java.util.List, java.util.Map, java.util.SortedSet, java.util.SortedMap 或者...任何你喜歡的類型!("任何你喜歡的類型" 代表你需要編寫 org.hibernate.usertype.UserCollectionType的實現(xiàn).)

          注意我們是如何用一個HashSet實例來初始化實例變量的.這是用于初始化新創(chuàng)建(尚未持久化)的類實例中集合值屬性的最佳方法。當(dāng)你持久化這個實例時——比如通過調(diào)用persist()——Hibernate 會自動把HashSet替換為Hibernate自己的Set實現(xiàn)。觀察下面的錯誤:

          Cat cat = new DomesticCat();
          Cat kitten = new DomesticCat();
          ....
          Set kittens = new HashSet();
          kittens.add(kitten);
          cat.setKittens(kittens);
          session.persist(cat);
          kittens = cat.getKittens(); //Okay, kittens collection is a Set
          (HashSet) cat.getKittens(); //Error!

          根據(jù)不同的接口類型,被Hibernate注射的持久化集合類的表現(xiàn)類似HashMap, HashSet, TreeMap, TreeSet or ArrayList

          集合類實例具有值類型的通常行為。當(dāng)被持久化對象引用后,他們會自動被持久化,當(dāng)不再被引用后,自動被刪除。假若實例被從一個持久化對象傳遞到另一個,它的元素可能從一個表轉(zhuǎn)移到另一個表。兩個實體不能共享同一個集合類實例的引用。因為底層關(guān)系數(shù)據(jù)庫模型的原因,集合值屬性無法支持空值語義;Hibernate對空的集合引用和空集合不加區(qū)別。

          你不需要過多的為此擔(dān)心。就如同你平時使用普通的Java集合類一樣來使用持久化集合類。只是要確認(rèn)你理解了雙向關(guān)聯(lián)的語義(后文討論)。

          7.2. 集合映射( Collection mappings )

          用于映射集合類的Hibernate映射元素取決于接口的類型。比如, <set> 元素用來映射Set類型的屬性。

          <class name="Product">
          <id name="serialNumber" column="productSerialNumber"/>
          <set name="parts">
          <key column="productSerialNumber" not-null="true"/>
          <one-to-many class="Part"/>
          </set>
          </class>

          除了<set>,還有<list>, <map>, <bag>, <array><primitive-array> 映射元素。<map>具有代表性:

          <map
          name="propertyName"                                         (1)
          table="table_name"                                          (2)
          schema="schema_name"                                        (3)
          lazy="true|false"                                           (4)
          inverse="true|false"                                        (5)
          cascade="all|none|save-update|delete|all-delete-orphan"     (6)
          sort="unsorted|natural|comparatorClass"                     (7)
          order-by="column_name asc|desc"                             (8)
          where="arbitrary sql where condition"                       (9)
          fetch="join|select|subselect"                               (10)
          batch-size="N"                                              (11)
          access="field|property|ClassName"                           (12)
          optimistic-lock="true|false"                                (13)
          node="element-name|."
          embed-xml="true|false"
          >
          <key .... />
          <map-key .... />
          <element .... />
          </map>
          (1)

          name 集合屬性的名稱

          (2)

          table (可選——默認(rèn)為屬性的名稱)這個集合表的名稱(不能在一對多的關(guān)聯(lián)關(guān)系中使用)

          (3)

          schema (可選) 表的schema的名稱, 他將覆蓋在根元素中定義的schema

          (4)

          lazy (可選--默認(rèn)為true) 可以用來關(guān)閉延遲加載,指定一直使用預(yù)先抓?。▽?shù)組不適用)

          (5)

          inverse (可選——默認(rèn)為false) 標(biāo)記這個集合作為雙向關(guān)聯(lián)關(guān)系中的方向一端。

          (6)

          cascade (可選——默認(rèn)為none) 讓操作級聯(lián)到子實體

          (7)

          sort(可選)指定集合的排序順序, 其可以為自然的(natural)或者給定一個用來比較的類。

          (8)

          order-by (可選, 僅用于jdk1.4) 指定表的字段(一個或幾個)再加上asc或者desc(可選), 定義Map,Set和Bag的迭代順序

          (9)

          where (可選) 指定任意的SQL where條件, 該條件將在重新載入或者刪除這個集合時使用(當(dāng)集合中的數(shù)據(jù)僅僅是所有可用數(shù)據(jù)的一個子集時這個條件非常有用)

          (10)

          fetch (可選, 默認(rèn)為select) 用于在外連接抓取、通過后續(xù)select抓取和通過后續(xù)subselect抓取之間選擇。

          (11)

          batch-size (可選, 默認(rèn)為1) 指定通過延遲加載取得集合實例的批處理塊大?。?batch size")。

          (12)

          access(可選-默認(rèn)為屬性property):Hibernate取得屬性值時使用的策略

          (12)

          樂觀鎖 (可選 - 默認(rèn)為 true): 對集合的狀態(tài)的改變會是否導(dǎo)致其所屬的實體的版本增長。 (對一對多關(guān)聯(lián)來說,關(guān)閉這個屬性常常是有理的)

          7.2.1. 集合外鍵(Collection foreign keys)

          集合實例在數(shù)據(jù)庫中依靠持有集合的實體的外鍵加以辨別。此外鍵作為集合關(guān)鍵字段(collection key column)(或多個字段)加以引用。集合關(guān)鍵字段通過<key> 元素映射。

          在外鍵字段上可能具有非空約束。對于大多數(shù)集合來說,這是隱含的。對單向一對多關(guān)聯(lián)來說,外鍵字段默認(rèn)是可以為空的,因此你可能需要指明 not-null="true"。

          <key column="productSerialNumber" not-null="true"/>

          外鍵約束可以使用ON DELETE CASCADE。

          <key column="productSerialNumber" on-delete="cascade"/>

          <key> 元素的完整定義,請參閱前面的章節(jié)。

          7.2.2. 集合元素(Collection elements)

          集合幾乎可以包含任何其他的Hibernate類型,包括所有的基本類型、自定義類型、組件,當(dāng)然還有對其他實體的引用。存在一個重要的區(qū)別:位于集合中的對象可能是根據(jù)“值”語義來操作(其聲明周期完全依賴于集合持有者),或者它可能是指向另一個實體的引用,具有其自己的生命周期。在后者的情況下,被作為集合持有的狀態(tài)考慮的,只有兩個對象之間的“連接”。

          被包容的類型被稱為集合元素類型(collection element type)。集合元素通過<element><composite-element>映射,或在其是實體引用的時候,通過<one-to-many><many-to-many>映射。前兩種用于使用值語義映射元素,后兩種用于映射實體關(guān)聯(lián)。

          7.2.3. 索引集合類(Indexed collections)

          所有的集合映射,除了set和bag語義的以外,都需要指定一個集合表的索引字段(index column)——用于對應(yīng)到數(shù)組索引,或者List的索引,或者Map的關(guān)鍵字。通過<map-key>,Map 的索引可以是任何基礎(chǔ)類型;若通過<map-key-many-to-many>,它也可以是一個實體引用;若通過<composite-map-key>,它還可以是一個組合類型。數(shù)組或列表的索引必須是integer類型,并且使用 <list-index>元素定義映射。被映射的字段包含有順序排列的整數(shù)(默認(rèn)從0開始)。

          <map-key
          column="column_name"                (1)
          formula="any SQL expression"        (2)
          type="type_name"                    (3)
          node="@attribute-name"
          length="N"/>
          (1)

          column(可選):保存集合索引值的字段名。

          (2)

          formula (可選): 用于計算map關(guān)鍵字的SQL公式

          (3)

          type (可選,默認(rèn)為整型integer):集合索引的類型。

          <map-key-many-to-many
          column="column_name"                (1)
          formula="any SQL expression"        (2)(3)
          class="ClassName"
          />
          (1)

          column(可選):集合索引值中外鍵字段的名稱

          (2)

          formula (可選): 用于計算map關(guān)鍵字的外鍵的SQL公式

          (3)

          class (必需):集合的索引使用的實體類。

          假若你的表沒有一個索引字段,當(dāng)你仍然希望使用List作為屬性類型,你應(yīng)該把此屬性映射為Hibernate <bag>。從數(shù)據(jù)庫中獲取的時候,bag不維護其順序,但也可選擇性的進行排序。

          從集合類可以產(chǎn)生很大一部分映射,覆蓋了很多常見的關(guān)系模型。我們建議你試驗schema生成工具,來體會一下不同的映射聲明是如何被翻譯為數(shù)據(jù)庫表的。

          7.2.4. 值集合于多對多關(guān)聯(lián)(Collections of values and many-to-many associations)

          任何值集合或者多對多關(guān)聯(lián)需要專用的具有一個或多個外鍵字段的collection table、一個或多個collection element column,以及還可能有一個或多個索引字段。

          對于一個值集合, 我們使用<element>標(biāo)簽。

          <element
          column="column_name"                     (1)
          formula="any SQL expression"             (2)
          type="typename"                          (3)
          length="N"
          precision="N"
          scale="N"
          not-null="true|false"
          unique="true|false"
          node="element-name"
          />
          (1)

          column(可選):保存集合元素值的字段名。

          (2)

          formula (可選): 用于計算元素的SQL公式

          (3)

          type (必需):集合元素的類型

          多對多關(guān)聯(lián)(many-to-many association) 使用 <many-to-many>元素定義.

          <many-to-many
          column="column_name"                               (1)
          formula="any SQL expression"                       (2)
          class="ClassName"                                  (3)
          fetch="select|join"                                (4)
          unique="true|false"                                (5)
          not-found="ignore|exception"                       (6)
          entity-name="EntityName"                           (7)
          node="element-name"
          embed-xml="true|false"
          />
          (1)

          column(可選): 這個元素的外鍵關(guān)鍵字段名

          (2)

          formula (可選): 用于計算元素外鍵值的SQL公式.

          (3)

          class (必需): 關(guān)聯(lián)類的名稱

          (3)

          outer-join (可選 - 默認(rèn)為auto): 在Hibernate系統(tǒng)參數(shù)中hibernate.use_outer_join被打開的情況下,該參數(shù)用來允許使用outer join來載入此集合的數(shù)據(jù)。

          (4)

          為此關(guān)聯(lián)打開外連接抓取或者后續(xù)select抓取。這是特殊情況;對于一個實體及其指向其他實體的多對多關(guān)聯(lián)進全預(yù)先抓?。ㄊ褂靡粭l單獨的SELECT),你不僅需要對集合自身打開join,也需要對<many-to-many>這個內(nèi)嵌元素打開此屬性。

          (5)

          對外鍵字段允許DDL生成的時候生成一個惟一約束。這使關(guān)聯(lián)變成了一個高效的一對多關(guān)聯(lián)。(此句存疑:原文為This makes the association multiplicity effectively one to many.)

          (6)

          not-found (可選 - 默認(rèn)為 exception): 指明引用的外鍵中缺少某些行該如何處理: ignore 會把缺失的行作為一個空引用處理。

          (7)

          entity-name (可選): 被關(guān)聯(lián)的類的實體名,作為class的替代。

          例子:首先, 一組字符串:

          <set name="names" table="NAMES">
          <key column="GROUPID"/>
          <element column="NAME" type="string"/>
          </set>

          包含一組整數(shù)的bag(還設(shè)置了order-by參數(shù)指定了迭代的順序):

          <bag name="sizes"
          table="item_sizes"
          order-by="size asc">
          <key column="item_id"/>
          <element column="size" type="integer"/>
          </bag>

          一個實體數(shù)組,在這個案例中是一個多對多的關(guān)聯(lián)(注意這里的實體是自動管理生命周期的對象(lifecycle objects),cascade="all"):

          <array name="addresses"
          table="PersonAddress"
          cascade="persist">
          <key column="personId"/>
          <list-index column="sortOrder"/>
          <many-to-many column="addressId" class="Address"/>
          </array>

          一個map,通過字符串的索引來指明日期:

          <map name="holidays"
          table="holidays"
          schema="dbo"
          order-by="hol_name asc">
          <key column="id"/>
          <map-key column="hol_name" type="string"/>
          <element column="hol_date" type="date"/>
          </map>

          一個組件的列表:(下一章討論)

          <list name="carComponents"
          table="CarComponents">
          <key column="carId"/>
          <list-index column="sortOrder"/>
          <composite-element class="CarComponent">
          <property name="price"/>
          <property name="type"/>
          <property name="serialNumber" column="serialNum"/>
          </composite-element>
          </list>

          7.2.5. 一對多關(guān)聯(lián)(One-to-many Associations)

          一對多關(guān)聯(lián)通過外鍵連接兩個類對應(yīng)的表,而沒有中間集合表。 這個關(guān)系模型失去了一些Java集合的語義:

          • 一個被包含的實體的實例只能被包含在一個集合的實例中

          • 一個被包含的實體的實例只能對應(yīng)于集合索引的一個值中

          一個從ProductPart的關(guān)聯(lián)需要關(guān)鍵字字段,可能還有一個索引字段指向Part所對應(yīng)的表。 <one-to-many>標(biāo)記指明了一個一對多的關(guān)聯(lián)。

          <one-to-many
          class="ClassName"                                  (1)
          not-found="ignore|exception"                       (2)
          entity-name="EntityName"                           (3)
          node="element-name"
          embed-xml="true|false"
          />
          (1)

          class(必須):被關(guān)聯(lián)類的名稱。

          (2)

          not-found (可選 - 默認(rèn)為exception): 指明若緩存的標(biāo)示值關(guān)聯(lián)的行缺失,該如何處理: ignore 會把缺失的行作為一個空關(guān)聯(lián)處理。

          (3)

          entity-name (可選): 被關(guān)聯(lián)的類的實體名,作為class的替代。

          例子

          <set name="bars">
          <key column="foo_id"/>
          <one-to-many class="org.hibernate.Bar"/>
          </set>

          注意:<one-to-many>元素不需要定義任何字段。 也不需要指定表名。

          重要提示:如果一對多關(guān)聯(lián)中的外鍵字段定義成NOT NULL,你必須把<key>映射聲明為not-null="true",或者使用雙向關(guān)聯(lián),并且標(biāo)明inverse="true"。參閱本章后面關(guān)于雙向關(guān)聯(lián)的討論。

          下面的例子展示一個Part實體的map,把name作為關(guān)鍵字。( partNamePart的持久化屬性)。注意其中的基于公式的索引的用法。

          <map name="parts"
          cascade="all">
          <key column="productId" not-null="true"/>
          <map-key formula="partName"/>
          <one-to-many class="Part"/>
          </map>

          7.3. 高級集合映射(Advanced collection mappings)

          7.3.1. 有序集合(Sorted collections)

          Hibernate支持實現(xiàn)java.util.SortedMapjava.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和某個實現(xiàn)了java.util.Comparator的類的名稱。

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

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

          <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的!

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

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

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

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

          一對多(one-to-many)

          Set或者bag值在一端, 單獨值(非集合)在另外一端

          多對多(many-to-many)

          兩端都是set或bag值

           

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

          這里有一個many-to-many的雙向關(guān)聯(lián)的例子;每一個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>

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

          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

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

          要建立一個一對多的雙向關(guān)聯(lián),你可以通過把一個一對多關(guān)聯(lián),作為一個多對一關(guān)聯(lián)映射到到同一張表的字段上,并且在"多"的那一端定義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="eg.Child">
          <id name="id" column="id"/>
          ....
          <many-to-one name="parent"
          class="Parent"
          column="parent_id"
          not-null="true"/>
          </class>

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

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

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

          <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>

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

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

          7.3.4. 使用<idbag>

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

          <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="eg.Person" outer-join="true"/>
          </idbag>

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

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

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

          7.4. 集合例子(Collection example)

          在前面的幾個章節(jié)的確非常令人迷惑。 因此讓我們來看一個例子。這個類:

          package eg;
          import java.util.Set;
          public class Parent {
          private long id;
          private Set children;
          public long getId() { return id; }
          private void setId(long id) { this.id=id; }
          private Set getChildren() { return children; }
          private void setChildren(Set children) { this.children=children; }
          ....
          ....
          }

          這個類有一個Child的實例集合。如果每一個子實例至多有一個父實例, 那么最自然的映射是一個one-to-many的關(guān)聯(lián)關(guān)系:

          <hibernate-mapping>
          <class name="Parent">
          <id name="id">
          <generator class="sequence"/>
          </id>
          <set name="children">
          <key column="parent_id"/>
          <one-to-many class="Child"/>
          </set>
          </class>
          <class name="Child">
          <id name="id">
          <generator class="sequence"/>
          </id>
          <property name="name"/>
          </class>
          </hibernate-mapping>

          在以下的表定義中反應(yīng)了這個映射關(guān)系:

          create table parent ( id bigint not null primary key )
          create table child ( id bigint not null primary key, name varchar(255), parent_id bigint )
          alter table child add constraint childfk0 (parent_id) references parent

          如果父親是必須的, 那么就可以使用雙向one-to-many的關(guān)聯(lián)了:

          <hibernate-mapping>
          <class name="Parent">
          <id name="id">
          <generator class="sequence"/>
          </id>
          <set name="children" inverse="true">
          <key column="parent_id"/>
          <one-to-many class="Child"/>
          </set>
          </class>
          <class name="Child">
          <id name="id">
          <generator class="sequence"/>
          </id>
          <property name="name"/>
          <many-to-one name="parent" class="Parent" column="parent_id" not-null="true"/>
          </class>
          </hibernate-mapping>

          請注意NOT NULL的約束:

          create table parent ( id bigint not null primary key )
          create table child ( id bigint not null
          primary key,
          name varchar(255),
          parent_id bigint not null )
          alter table child add constraint childfk0 (parent_id) references parent

          另外,如果你絕對堅持這個關(guān)聯(lián)應(yīng)該是單向的,你可以對<key>映射聲明NOT NULL約束:

          <hibernate-mapping>
          <class name="Parent">
          <id name="id">
          <generator class="sequence"/>
          </id>
          <set name="children">
          <key column="parent_id" not-null="true"/>
          <one-to-many class="Child"/>
          </set>
          </class>
          <class name="Child">
          <id name="id">
          <generator class="sequence"/>
          </id>
          <property name="name"/>
          </class>
          </hibernate-mapping>

          另外一方面,如果一個子實例可能有多個父實例, 那么就應(yīng)該使用many-to-many關(guān)聯(lián):

          <hibernate-mapping>
          <class name="Parent">
          <id name="id">
          <generator class="sequence"/>
          </id>
          <set name="children" table="childset">
          <key column="parent_id"/>
          <many-to-many class="Child" column="child_id"/>
          </set>
          </class>
          <class name="Child">
          <id name="id">
          <generator class="sequence"/>
          </id>
          <property name="name"/>
          </class>
          </hibernate-mapping>

          表定義:

          create table parent ( id bigint not null primary key )
          create table child ( id bigint not null primary key, name varchar(255) )
          create table childset ( parent_id bigint not null,
          child_id bigint not null,
          primary key ( parent_id, child_id ) )
          alter table childset add constraint childsetfk0 (parent_id) references parent
          alter table childset add constraint childsetfk1 (child_id) references child
          posted on 2007-04-03 10:32 ???MengChuChen 閱讀(704) 評論(0)  編輯  收藏 所屬分類: hibernate
          主站蜘蛛池模板: 政和县| 时尚| 郴州市| 龙岩市| 南阳市| 西乡县| 寻乌县| 英德市| 万年县| 辽阳市| 马关县| 伊宁县| 沧州市| 景德镇市| 东平县| 邢台市| 虎林市| 章丘市| 新平| 滦南县| 阳城县| 莎车县| 新源县| 雷州市| 杭锦后旗| 乌拉特前旗| 山丹县| 修武县| 安图县| 富民县| 饶河县| 平遥县| 新乡县| 太白县| 辽阳市| 德庆县| 马龙县| 永登县| 建平县| 乌拉特中旗| 永兴县|