咱們介紹了一對一的單向關聯映射,單向是指只能從人(Person)這端加載身份證端(IdCard),可是反過來,不能從身份證端加載人得信息。如圖所示:html
![](http://static.javashuo.com/static/loading.gif)
關鍵緣由在於對象模型具備方向性:java
單向:一端只能加載另外一端,不能反過來。數據庫
雙向:兩端均可以加載另外一端。app
問題來了:如何咱們想從身份證端(IdCard)加載人(Person),怎麼辦呢?測試
下面咱們開始介紹一對一的雙向關聯映射。fetch
映射原理
雙向關聯映射與單向關聯映射的原理是同樣的,雙向關聯映射並不影響存儲,隻影響加載。因此,雙向關聯映射和單向關聯映射的關係模型是同樣的即數據庫的表結構是同樣的,只是IdCard的實體類和配置文件(IdCard.hbm.xml)發生了一點點變化。this
對象模型
![](http://static.javashuo.com/static/loading.gif)
從上圖中能夠看出:spa
一、一我的只有一張身份證,惟一的一個身份證號,對象之間是一對一的關係;.net
二、兩個對象得關係維護仍是由person端決定(由於關係只能由一端維護主鍵,不然關係就亂了)。hibernate
根據上面的對象模型,咱們能夠看到Person端沒有變化,可是要在IdCard端加上Person的引用,例如Person和IdCard實體類以下。
Person
[html] view plain copy
- package com.liang.hibernate;
-
- public class Person {
- private int id;
- private String name;
- private IdCard idCard;
-
- public IdCard getIdCard() {
- return idCard;
- }
- public void setIdCard(IdCard idCard) {
- this.idCard = idCard;
- }
- public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- }
IdCard
[java] view plain copy
- package com.liang.hibernate;
-
- public class IdCard {
- private int id;
- private String cardNo;
- private Person person;
-
- public Person getPerson() {
- return person;
- }
- public void setPerson(Person person) {
- this.person = person;
- }
- public int getId() {
- return id;
- }
-
- public void setId(int id) {
- this.id = id;
- }
- public String getCardNo() {
- return cardNo;
- }
- public void setCardNo(String cardNo) {
- this.cardNo = cardNo;
- }
- }
不管是單向關聯映射仍是雙向關聯映射,他們都屬於一對一關聯映射,只是他們主鍵的生成策略不一樣,分爲主鍵關聯映射和惟一外鍵關聯映射。
因爲它們都屬於一對一關聯映射,因此,Hibernate封裝雙向關聯映射時,主鍵關鍵映射和惟一外鍵關聯映射的加載策略同樣,都採用的是一對一<one-to-one name=""></one-to-one>,只是屬性設置不一致,因此,下面咱們分開來看IdCard的配置文件。
分類:
主鍵關聯映射
同一對一單向關聯映射相似,主鍵關聯即利用主鍵進行關聯,關聯主鍵的值相同。下面咱們看一下映射文件:
IdCard.hbm.xml
[html] view plain copy
- <?xml version="1.0"?>
- <!DOCTYPE hibernate-mapping PUBLIC
- "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
- <hibernate-mapping package="com.liang.hibernate">
- <class name="IdCard" table="t_idCard">
- <id name="id">
- <generator class="native"></generator>
- </id>
- <property name="cardNo"></property>
- <!-- 怎麼加載對象,抓取策略:join聯合查詢(默認),select:一條條的查詢 -->
- <one-to-one name="person" class="Person" fetch="join"></one-to-one>
- </class>
- </hibernate-mapping>
Person.hbm.xml,同一對一單向主鍵關聯映射同樣
[html] view plain copy
- <?xml version="1.0"?>
- <!DOCTYPE hibernate-mapping PUBLIC
- "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
- <hibernate-mapping package="com.liang.hibernate">
- <class name="Person" table="t_person">
- <id name="id">
- <!-- 採用foreign生成策略,forgeign會取得關聯對象的標識 -->
- <generator class="foreign" >
- <param name="property">idCard</param>
- </generator>
- </id>
- <property name="name"></property>
- <!--
- one-to-one指示hibernate如何加載其關聯對象,默認根據主鍵加載
- 也就是拿到關係字段值,根據對端的主鍵來加載關聯對象
-
- constrained="true"表示,當前主鍵(person的主鍵)仍是一個外鍵
- 參照了對端的主鍵(IdCard的主鍵),也就是會生成外鍵約束語句
- -->
- <one-to-one name="idCard" class="IdCard" constrained="true"></one-to-one>
- </class>
- </hibernate-mapping>
生成的表結構
![](http://static.javashuo.com/static/loading.gif)
惟一外鍵關聯映射
一對一雙向關聯映射的外鍵關聯映射也與一對一單向關聯映射的外鍵關聯映射相似,在其一對一的指向端(Person)存在一個惟一外鍵,該惟一外鍵與被指向端(IdCard)相關聯,關聯主鍵的值相同。下面咱們看一下映射文件:
IdCard.hbm.xml
[html] view plain copy
- <?xml version="1.0"?>
- <!DOCTYPE hibernate-mapping PUBLIC
- "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
- <hibernate-mapping package="com.liang.hibernate">
- <class name="IdCard" table="t_idCard">
- <id name="id">
- <generator class="native"></generator>
- </id>
- <property name="cardNo"></property>
- <!-- 一對一惟一外鍵關聯雙向採用<one-to-one>標籤來映射,必須指定<one-to-one>
- 標籤中的property-ref屬性爲關係字段的名稱
- -->
- <one-to-one name="person" class="Person" property-ref="idCard"></one-to-one>
- </class>
- </hibernate-mapping>
Person.hbm.xml,同一對一單向惟一外鍵關聯映射同樣
[html] view plain copy
- <?xml version="1.0"?>
- <!DOCTYPE hibernate-mapping PUBLIC
- "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
- <hibernate-mapping package="com.liang.hibernate">
- <class name="Person" table="t_person">
- <id name="id">
- <generator class="native" ></generator>
- </id>
- <property name="name"></property>
- <!-- 因爲它是一對一的惟一外鍵關聯,它是多對一關聯的特例,註釋能夠直接寫成多對一關聯-->
- <!-- idCard屬性,表達的是本對象與IdCard的多對一關係。 -->
- <many-to-one name="idCard" class="IdCard" column="idCardId" unique="true"></many-to-one>
- </class>
- </hibernate-mapping>
生成的表結構
![](http://static.javashuo.com/static/loading.gif)
對比
一對一單向和雙向關聯映射的區別正是對象模型和關係模型的區別之一。
對象模型:有方向性。它究竟是單向仍是雙向是由對象模型決定的即配置文件決定。
關係模型:沒有方向性或者說是雙向的。從任何一端均可以加載另外一端。
下載
以上內容,只證實了一對一雙向關聯映射不影響存儲即沒有改變表結構,但不能證實關聯是雙向的,須要寫相應的測試用例,咱們以源碼的形式給你們。源碼下載
總結
一對一雙向關聯映射並非必須的,是由需求下決定的。若是沒有這樣的需求,用戶也沒有要求,系統也不須要,就沒有必要創建雙向的關聯映射。
下篇博文,咱們介紹多對多單向關聯映射,謝謝關注