Hibernate4实战 之 第四部分:关系映射
生活随笔
收集整理的這篇文章主要介紹了
Hibernate4实战 之 第四部分:关系映射
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
數據表之間的關系分為三類:一對一、一對多、多對多 一對一數據表(部門表? 和? 部門主管表) 一對多數據表(部門表? 和? 部門下的人員表) 多對多數據表(部門表? 和? 人員表) 根據相互尋找的關系又分:單向和雙向 對象一對一 (雙向)
java代碼: 查看復制到剪貼板打印public?class?A?{?? private?B?b?=?null;??}?? public?class?B?{?? private?A?a?=?null;??}?? n對象一對多?(雙向)?? public?class?A?{?? private?B?b?=?null;??}?? public?class?B?{?? private?Collection<A>?colA?=?null;??}?? n對象多對多?(雙向)?? public?class?A?{?? private?Collection<B>?colB?=?null;??}?? public?class?B?{?? private?Collection<A>?colA?=?null;??}?? 雙向一對多是最常用的映射關系 <key>元素 <key> 元素在父映射元素定義了對新表的連接,并且在被連接表中定義了一個外鍵引用原表的主鍵的情況下經常使用。
java代碼: 查看復制到剪貼板打印<key?? column="columnname"(1)?? on-delete="noaction|cascade"(2)?? property-ref="propertyName"(3)?? not-null="true|false"(4)?? update="true|false"(5)?? unique="true|false"(6)?? />?? (1)column(可選):外鍵字段的名稱。也可以通過嵌套的 <column> 指定。 (2)on-delete(可選,默認是 noaction):表明外鍵關聯是否打開數據庫級別的級聯刪除。 (3)property-ref(可選):表明外鍵引用的字段不是原表的主鍵(提供給遺留數據)。 (4)not-null(可選):表明外鍵的字段不可為空,意味著無論何時外鍵都是主鍵的一部分。 (5)update(可選):表明外鍵決不應該被更新,這意味著無論何時外鍵都是主鍵的一部分。 (6)unique(可選):表明外鍵應有唯一性約束,這意味著無論何時外鍵都是主鍵的一部分。 對那些看重刪除性能的系統,推薦所有的鍵都應該定義為 on-delete="cascade",這樣Hibernate 將使用數據庫級的 ON CASCADE DELETE 約束,而不是多個 DELETE 語句用于映射集合類的 Hibernate映射元素取決于接口的類型。比如,<set>元素用來映射Set類型的屬性:
java代碼: 查看復制到剪貼板打印<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>具有代表性 ,如下:
java代碼: 查看復制到剪貼板打印<map?? name="propertyName"?(1)?? table="table_name"?(2)?? schema="schema_name"?(3)?? lazy="true|extra|false"?(4)?? inverse="true|false"?(5)?? cascade=“all|none|save-update|delete|all-delete-orphan|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)?? mutable="true|false"?(14)?? >?? <key?....?/>?<map-key?....?/>?? <element?....?/>?? </map>?? (1) name 集合屬性的名稱 (2) table (可選——默認為屬性的名稱)這個集合表的名稱(不能在一對多的關聯關系中使用) (3) schema (可選) 表的schema的名稱, 他將覆蓋在根元素中定義的schema (4) lazy (可選--默認為true) 可以用來關閉延遲加載(false), (5) inverse (可選——默認為false) 標記這個集合作為雙向關聯關系中的方向一端。 (6) cascade (可選——默認為none) 讓操作級聯到子實體 (7) sort(可選)指定集合的排序順序 (8) order-by (可選, 僅用于jdk1.4) 指定表的字段(一個或幾個)再加上asc或者desc(可選), 定義Map,Set和Bag的迭代順序 (9) where (可選) 指定任意的SQL where條件, 該條件將在重新載入或者刪除這個集合時使用(當集合中的數據僅僅是所有可用數據的一個子集時這個條件非常有用) (10) fetch (可選, 默認為select) 用于在外連接抓取、通過后續select抓取和通過后續subselect抓取之間選擇。 (11) batch-size (可選, 默認為1) 指定通過延遲加載取得集合實例的批處理塊大小 (12) access(可選-默認為屬性property):Hibernate取得集合屬性值時使用的策略 (13) 樂觀鎖 (可選 - 默認為 true): 對集合的狀態的改變會是否導致其所屬的實體的版本增長。 (對一對多關聯來說,關閉這個屬性常常是有理的) (14) mutable(可變) (可選 - 默認為true): 若值為false,表明集合中的元素不會改變(在某些情況下可以進行一些小的性能優化)。 集合外鍵 集合實例在數據庫中依靠持有集合的實體的外鍵加以辨別。此外鍵作為集合關鍵字段加以引用。集合關鍵字段通過 <key> 元素映射。 在外鍵字段上可能具有非空約束。對于大多數集合來說,這是隱含的。對單向一對多關聯來說,外鍵字段默認是可以為空的,因此你可能需要指明 not-null=“true”。示例如下:
java代碼: 查看復制到剪貼板打印<key?column="productSerialNumber"?not-null="true"/>?? 外鍵約束可以使用 ON DELETE CASCADE,示例如下:
java代碼: 查看復制到剪貼板打印<key?column="productSerialNumber"?on-delete="cascade"/>?? one-to-one?? 通過 one-to-one 元素,可以定義持久化類的一對一關聯。
java代碼: 查看復制到剪貼板打印<one-to-one?? name="propertyName"(1)?? class="ClassName"(2)?? cascade="cascade_style"(3)?? constrained="true|false"(4)?? fetch="join|select"(5)?? property-ref="propertyNameFromAssociatedClass"(6)?? access="field|property|ClassName"(7)?? formula="any?SQL?expression"(8)?? lazy="proxy|no-proxy|false"(9)?? entity-name="EntityName"(10)?? />?? (1)name:屬性名。 (2)class(可選 — 默認是通過反射得到的屬性類型):被關聯的類的名字。 (3)cascade(級聯)(可選)表明操作是否從父對象級聯到被關聯的對象。 (4)constrained(約束)(可選)表明該類對應的表對應的數據庫表,和被關聯的對象所對應的數據庫表之間,通過一個外鍵引用對主鍵進行約束。 這個選項影響 save() 和 delete() 在級聯執行時的先后順序以及決定該關聯能否被委托(也在 schema export tool 中被使用)。 (5)fetch(可選 — 默認為 select):在外連接抓取(outer-join fetching)和序列選擇抓取(sequential select fetching)兩者中選擇其一。 (6)property-ref:(可選)指定關聯類的屬性名,這個屬性將會和本類的主鍵相對應。如果沒有指定,會使用對方關聯類的主鍵。 (7)access(可選 — 默認為 property):Hibernate 用來訪問屬性值的策略。 (8)formula (可選):絕大多數一對一的關聯都指向其實體的主鍵。在一些少見的情況中,你可能會指向其他的一個或多個字段,或者是一個表達式,這些情況下,你可以用一 個 SQL 公式來表示。(可以在 org.hibernate.test.onetooneformula 找到例子) (9)lazy(可選 — 默認為 proxy):默認情況下,單點關聯是經過代理的。lazy="no-proxy"指定此屬性應該在實例變量第一次被訪問時應該延遲抓取(fetche lazily)(需要運行時字節碼的增強)。 lazy="false"指定此關聯總是被預先抓取。注意,如果constrained="false", 不可能使用代理,Hibernate會采取預先抓取。 (10)entity-name(可選):被關聯的類的實體名。 nmany-to-one 通過 many-to-one 元素,可以定義一種常見的與另一個持久化類的多對一關聯,這個表的一個外鍵引用目標表的主鍵字段。
java代碼: 查看復制到剪貼板打印<many-to-one?? name="propertyName"?(1)?? column="column_name"?(2)??? class="ClassName"?(3)?? cascade="cascade_style"(4)?? fetch="join|select"?(5)?? update="true|false"?(6)?? insert="true|false"?(7)?? property-ref="propertyNameFromAssociatedClass"(8)?? access="field|property|ClassName"(9)?? unique="true|false"?(10)?? not-null="true|false"?(11)?? optimistic-lock="true|false“?(12)?? lazy="proxy|no-proxy|false"?(13)?? not-found="ignore|exception“?(14)?? entity-name="EntityName"?(15)?? formula="arbitrary?SQL?expression"(16)?? />?? ??? (1)name:屬性名。 (2)column(可選):外鍵字段的名稱。也可以通過嵌套的 <column> 指定。 (3)class(可選 — 默認是通過反射得到的屬性類型):被關聯的類的名字。 (4)cascade(級聯)(可選)表明操作是否從父對象級聯到被關聯的對象。 (5)fetch(可選 — 默認為 select):在外連接抓取和序列選擇抓取兩者中選擇其一。 (6)update, insert(可選 — 默認為 true)指定對應的字段是否包含在用于 UPDATE 和/或 INSERT的 SQL 語句中。如果二者都是false,則這是一個純粹的 “外源性(derived)”關聯,它的值是通過 映射到同一個(或多個)字段的某些其他屬性得到 或者通過 trigger(觸發器)、或其他程序生成。 (7)property-ref:(可選)被關聯到此外鍵的類中的對應屬性的名字。如果不指定,使用被關聯類的主鍵 (8)access(可選 — 默認為 property):Hibernate 用來訪問屬性值的策略。 (9)unique(可選):使用 DDL 為外鍵字段生成一個唯一約束。此外, 這也可以用作 propertyref的目標屬性。這使關聯同時具有一對一的效果。 (10)not-null(可選):使用 DDL 為外鍵字段生成一個非空約束。 (11)optimistic-lock(可選 — 默認為 true):指定這個屬性在做更新時是否需要獲得樂觀鎖定。換句話說,它決定這個屬性發生臟數據時版本(version)的值是否增長。 (12)lazy(可選 — 默認為 proxy):默認情況下,單點關聯是經過代理的。lazy="no-proxy" 指定此屬性應該在實例變量第一次被訪問時應該延遲抓取(fetche lazily)(需要運行時字節碼的增強)。lazy="false" 指定此關聯總是被預先抓取。 (13)not-found(可選 - 默認為exception):指定如何處理引用缺失行的外鍵:ignore 會把缺失的行作為一個空關聯處理。 (14)entity-name(可選):被關聯的類的實體名。 (15)formula(可選):SQL 表達式,用于定義 computed(計算出的)外鍵值。 one-to-many 通過 one-to-many 元素,可以定義一種常見的與另一個持久化類的一對多關聯。
java代碼: 查看復制到剪貼板打印<one-to-many?? class="ClassName"(1)?? not-found="ignore|exception"(2)?? entity-name="EntityName"(3)?? />?? (1)class(必需):被關聯類的名稱。 (2)not-found(可選 - 默認為exception):指明若緩存的標示值關聯的行缺失,該如何處理:ignore 會把缺失的行作為一個空關聯處理。 (3)entity-name(可選):被關聯的類的實體名,作為 class 的替代。 注意:<one-to-many> 元素不需要定義任何字段。也不需要指定表名。 還是用示例來看,下面作一個雙向一對多的關系示例: 1:新建一個Parent對象和Child對象,Parent對象里面有一個Child對象的集合,Child對象里面有一個對Parent對象的引用,如下:
java代碼: 查看復制到剪貼板打印public?class?Parent{?? ??private?String?id;?? ??private?String?name;?? ??private?Set?children?=?new?HashSet();?? ……?? }?? public?class?Child?{?? ??private?String?uuid;?? ??private?String?address;?? ??private?String?postCode;?? ??private?Parent?parent;?? ……?? }?? Parent.hbm.xml:?? <?xml?version="1.0"?encoding="UTF-8"?>?? <!DOCTYPE?hibernate-mapping?PUBLIC?? ????"-//Hibernate/Hibernate?Mapping?DTD?3.0//EN"?? ????"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">?? <hibernate-mapping>?? ????<class?name="cn.javass.h3.parentchild.Parent"?table="tbl_parent"?dynamic-update="true"?dynamic-insert="true"?lazy="true">?? ????????<id?name="id"?column="uuid"?type="java.lang.String"?unsaved-value="any">?? ????????????<generator?class="assigned">?</generator>?? ????????</id>?? ????????<property?name="name"??update="true"?insert="true"/>????????? <set?name="children"?inverse="true"??cascade="all">?? <key?column="tbl_parent_fk"/>?? <one-to-many?class="cn.javass.h3.parentchild.Child"/>?? </set>?? ????</class>?? </hibernate-mapping>?? ??? Child.hbm.xml:?? <?xml?version="1.0"?encoding="UTF-8"?>?? <!DOCTYPE?hibernate-mapping?PUBLIC?? ????"-//Hibernate/Hibernate?Mapping?DTD?3.0//EN"?? ????"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">?? <hibernate-mapping>?? ????<class?name="cn.javass.h3.parentchild.Child"?table="tbl_child"?dynamic-update="true"?dynamic-insert="true"?lazy="true">?? ????????<id?name="uuid"?column="uuid"?type="java.lang.String"?unsaved-value="any">?? ????????????<generator?class="assigned">?</generator>?? ????????</id>?? ????????<property?name="address"??update="true"?insert="true"/>?? <property?name="postCode"??update="true"?insert="true"/>?? <many-to-one?? name="parent"?? column="tbl_Parent_fk"?? class="cn.javass.h3.parentchild.Parent"?? not-null="true"?? />?? ????</class>?? </hibernate-mapping>?? 客戶端測試TestMR.java文件太長,直接看演示好了。 在這個測試里面分別演示了單獨的操作和級聯的操作。 inverse:指定由哪一方來維護雙方的關聯關系,默認是false,也就是雙方都維護,主要用在一對多 和 多對多中。 在一對多中使用inverse的時候,通常是在”一”這一端設置inverse=true,他的意思就是由多的那一端去維護關系,非反向端用于把內存中的表示保存到數據庫中。如下: Parent p = new Parent(); Child c = new Child(); c.setParent(p); //維護父子之間關系 p.getChildren().add(c); ninverse還有一個重要特點就是會優化Sql ncascade:定義對象的級聯關系 all : 所有情況下均進行關聯操作 none:所有情況下均不進行關聯操作。這是默認值 save-update:在執行save/update/saveOrUpdate時進行關聯操作 delete:在執行delete時進行關聯操作 簡單的示范一下雙向的一對一 雙向一對一的操作是類似于雙向一對多的,只是配置上有一些不同: 1:Parent里面的配置,示例如下: <one-to-one name= “cc” class= “cn.javass.h3.parentchild.Child” cascade= “all”? property-ref= “parent“/>這里的property-ref參照的是Child對象里面的屬性。 2:Child里面的配置,不是使用one-to-one,而是仍使用many-to-one,示例如下: <many-to-one name=“parent” class=“cn.javass.h3.parentchild.Parent” column=“tbl_parent_fk”/> 3:測試程序里面,原來調用集合的地方,變成調用一個Child對象,其他就差不多了,可以測試看看。 Hibernate4的過濾器 Hibernate3 新增了對某個類或者集合使用預先定義的過濾器條件(filter criteria)的功能。過濾器條件相當于定義一個 非常類似于類和各種集合上的“where”屬性的約束子句, 但是過濾器條件可以帶參數,應用程序可以在運行時決 定是否啟用給定的過濾器,以及使用什么樣的參數值。過濾器的用法很像數據庫視圖,只不過是在應用程序中確定使用什么樣的參數的。 定義過濾器 要使用過濾器,首先要在相應的映射節點中定義。而定義一個過濾器,要用到位于 <hibernatemapping/>節點之內的 <filter-def/> 節點: 示例如下:
java代碼: 查看復制到剪貼板打印<filter-def?name="myFilter">?? <filter-param?name="myFilterParam"?type="string"/>?? </filter-def>?? 使用過濾器之配置 定義好之后,就可以在某個類中使用這個過濾器:
java代碼: 查看復制到剪貼板打印<class?name="myClass"?...>?? ...?? <filter?name="myFilter"?condition=":myFilterParam=FILTERED_COLUMN"/>?? </class>?? 或者也可以在某個集合使用它:
java代碼: 查看復制到剪貼板打印<set?...>?? <filter?name="myFilter"?condition=":myFilterParam=FILTERED_COLUMN"/>?? </set>?? 在同時可以使用多個過濾器。 使用過濾器之程序 在程序中,需要使用session接口中的:enableFilter(String filterName),getEnabledFilter(String filterName),和 disableFilter(String filterName)方法。Session中默認不啟用過濾器,必須通過enabledFilter() 方法顯式的啟用。 示例代碼session.enableFilter("myFilter").setParameter("myFilterParam", "some-value"); 過濾器示例 在Parent.hbm.xml中定義有如下的過濾器:
java代碼: 查看復制到剪貼板打印<filter-def?name="myFilter">?? <filter-param?name="myFilterParam"?type="string"/>?? </filter-def>?? <filter-def?name="myFilter2">?? <filter-param?name="myFilterParam"?type="int"/>?? <filter-param?name="myFilterParam2"?type="int"/>?? </filter-def>?? 在定義Child集合中使用
java代碼: 查看復制到剪貼板打印<set?name="children"?inverse="true"?cascade="all"?fetch="select"?lazy="false"?batch-size="3">?? <key?column="tbl_parent_fk"/>?? <one-to-many?class="cn.javass.h3.parentchild.Child"?/>?? <filter?name="myFilter"?? condition="address?like?:myFilterParam"></filter>?? <filter?name="myFilter2"?condition="uuid?>=?:myFilterParam?and?uuid?<=?:myFilterParam2"></filter>?? </set>?? 程序中使用示例
java代碼: 查看復制到剪貼板打印s.enableFilter("myFilter").setParameter("myFilterParam",?"%1%");?? s.enableFilter("myFilter2").setParameter("myFilterParam",?1)?? .setParameter("myFilterParam2",?3);?? Query?q?=?s.createQuery("select?p?from?Parent?as?p??");?? System.out.println("p==="+p.getChildren());?? ??? 視頻配套PPT,視頻地址【 Hibernate4實戰-獨家視頻課程 】 原創內容 轉自請注明【 http://***/forum/blogPost/list/2479.html#7154】
java代碼: 查看復制到剪貼板打印
java代碼: 查看復制到剪貼板打印
java代碼: 查看復制到剪貼板打印
java代碼: 查看復制到剪貼板打印
java代碼: 查看復制到剪貼板打印
java代碼: 查看復制到剪貼板打印
java代碼: 查看復制到剪貼板打印
java代碼: 查看復制到剪貼板打印
java代碼: 查看復制到剪貼板打印
java代碼: 查看復制到剪貼板打印
java代碼: 查看復制到剪貼板打印
java代碼: 查看復制到剪貼板打印
java代碼: 查看復制到剪貼板打印
java代碼: 查看復制到剪貼板打印
java代碼: 查看復制到剪貼板打印
java代碼: 查看復制到剪貼板打印
轉載于:https://www.cnblogs.com/zdh-ry/archive/2012/07/09/2583778.html
總結
以上是生活随笔為你收集整理的Hibernate4实战 之 第四部分:关系映射的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何创建XML文件
- 下一篇: 8个最好的Linux平台商业智能(BI)