本篇部落格介紹一下hibernate中一對一關聯映射的配置和使用,一對一關聯映射分為單向一對一關系和雙向一對一關系,單向一對一分為唯一外鍵關聯映射和主鍵關聯映射,雙向一對一分為雙向主鍵關聯和雙向外鍵關聯,下面介紹這四種關聯映射。
一、單向一對一關系映射
(1)唯一外鍵關聯映射
唯一外鍵是表中每一行外鍵唯一對應着另一個表中的主鍵,也就是說另一個表的主鍵唯一作為另一個表的外鍵,關系如下所示:
一個人對應着一個身份證,省份證表的id是人實體表中的外鍵,這種實作類似乎多對一映射,一個表的主鍵辨別列是另一個表的外鍵,使用<many-to-one>标簽,但是這裡應該采用的是唯一對應,此時應該設定它的屬性來做唯一辨別,需要在<many-to-one>标簽中加上屬性unique,指定多的一端的unique值為true。是以需要在person的映射檔案中設定一個<many-to-one name="idCard" unique="true">.對應的Person.hbm.xml代碼為:
<hibernate-mapping>
<class name="com.hibernate.Person" table="t_person">
<id name="id" type="int">
<generator class="native"/>
</id>
<property name="name"></property>
<many-to-one name="idCard" unique="true"></many-to-one>
</class>
</hibernate-mapping>
(2)主鍵關聯映射
一對一關聯映射還存在一種情況就是一個表的主鍵同時也是另外一個表的外鍵,并且是唯一的,就是說一個表的字段同時是主鍵和外鍵,關系如下所示:
t_person裡面的主鍵同時對應t_idCard裡面的外鍵,兩個表的id是一一對應的。使用<one-to-one>的關系,<param name="property">idCard</param>指的是在Person.java中有一個idCard的屬性,該屬性是Person對象的一個關聯對象,是以需要注冊到foreign中,取得關聯對象的辨別。另外在<one-to-one>标簽中添加了一個屬性constrained="true",訓示了Person對象的主鍵同時又是一個外鍵,需要注意建立Person類時需要添加idCard屬性。
person.hbm.xml代碼:
<hibernate-mapping>
<class name="com.hibernate.Person" table="t_person">
<id name="id">
<!-- 采用foreign生成政策,forgeign會取得關聯對象的辨別 -->
<generator class="foreign">
<!-- property隻關聯對象 -->
<param name="property">idCard</param>
</generator>
</id>
<property name="name"/>
<!--
one-to-one訓示hibernate如何加載其關聯對象,預設根據主鍵加載
也就是拿到關系字段值,根據對端的主鍵來加載關聯對象
constrained="true表示,目前主鍵(person的主鍵)還是一個外鍵
參照了對端的主鍵(IdCard的主鍵),也就是會生成外鍵限制語句
-->
<one-to-one name="idCard" constrained="true"/>
</class>
</hibernate-mapping>
IdCard.hbm.xml代碼如下:
<hibernate-mapping>
<class name="com.hibernate.IdCard" table="t_idCard">
<id name="id">
<generator class="native"/>
</id>
<property name="cardNo"/>
<one-to-one name="person"/>
</class>
</hibernate-mapping>
二、雙向一對一關系映射
(1)雙向主鍵關聯
雙向主鍵關聯其實是單向一對一關聯映射的一種特殊情況,不同的是要在關聯對象的兩端的配置檔案中都要進行<one-to-one>的配置。一個人對應着一個唯一的身份證,一個身份證也唯一映射着一個人,這就是一種雙向的關聯關系,person的主鍵同樣也是IDcard的主鍵,是主鍵的同時為外鍵,關系如下所示:
Person.hbm.xml映射檔案,該檔案中主鍵生成政策沒有特殊的要求,因為它和IdCard類互相制約的關系,它的主鍵和外鍵都是IdCard的主鍵,另外因為是一對一關系是以要在映射檔案中添加<one-to-one>标簽。
<hibernate-mapping>
<class name="com.src.hibernate.Person" table="t_Person">
<id name="id" type="int" column="personId">
<generator class="native"></generator>
</id>
<property name="name" type="string" column="personName"></property>
<!--
one-to-one标簽訓示Hibernate如何加載其關聯對象,預設根據主鍵加載,也就是拿到關系字段值,根據對端的主鍵來加載關聯對象
-->
<one-to-one name="idcard"></one-to-one>
</class>
</hibernate-mapping>
IdCard.hbm.xml映射檔案,在映射檔案中添加外鍵屬性person,并添加對應的<one-to-one>标簽,目的是強制限制person類來實作一對一的映射關系,最後在映射中将constrained屬性設為true,保證強制限制關系。
<hibernate-mapping>
<class name="com.src.hibernate.IdCard" table="t_idCard">
<id name="id" type="int" column="personId">
<generator class="foreign">
<param name="property">person</param>
</generator>
</id>
<property name="cardNo" type="string" column="cardno"></property>
<one-to-one name="person" constrained="true"></one-to-one>
</class>
</hibernate-mapping>
idCard.java類, IdCard類和Person類之間有一對一的關聯關系是以要在IdCard類中添加對應的Person屬性,這是為了能在映射檔案中的外鍵中添加對應的屬性,設定對應的外鍵關聯類。
public class IdCard {
private int id;
private String cardNo;
private 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;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
}
Person.java類,在該類中除了添加基本的屬性外還要添加對應的IdCard類作為屬性,因為它們之間是一對一的雙向關聯關系,是以在Person類中同樣要添加IdCard類,相同的道理IdCard類中同樣添加了Person類屬性。
public class Person {
private int id;
private String name;
private 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;
}
public IdCard getIdCard() {
return idCard;
}
public void setIdCard(IdCard idCard) {
this.idCard = idCard;
}
}
(2)雙向一對一關聯映射
雙向一對一關聯映射可以了解為外鍵關聯的一種特殊情況,隻不過是一種雙向的對應關系。任何身份證是一對一的關系,person表中有idCard表的主鍵,也就是說通過person可以擷取到IDCard,通過idCard也可以擷取到person,并且他們的關系是雙向的,它們的關系如下圖所示:
對象模型:
關系模型:
idCard.hbm.xml映射檔案,idCard表不是映射的主表,是以在做一對一的映射時需要使用的是<one-to-one>标簽來配置,并且需要制定person關系模型中的外鍵屬性,idCard映射檔案如下:
<hibernate-mapping>
<class name="com.src.hibernate.IdCard" table="t_idCard">
<id name="id" type="int">
<generator class="native" />
</id>
<property name="cardNo" type="java.lang.String">
<column name="CARDNO" />
</property>
<one-to-one name="person" property-ref="idCard"></one-to-one>
</class>
</hibernate-mapping>
Person.hbm.xml映射檔案,person表是映射的主表,需要在該表中添加一個外鍵屬性列來标示idCard表,是以這裡需要使用<many-to-one>标簽,在person對象中生成相應的外鍵,并且還要使用unique表示屬性唯一。
<hibernate-mapping>
<class name="com.src.hibernate.Person" table="t_person">
<id name="id" type="int" column="personId">
<generator class="native" />
</id>
<property name="name" type="java.lang.String">
<column name="NAME" />
</property>
<many-to-one name="idCard" column="idCardNo" unique="true" not-null="true"></many-to-one>
</class>
</hibernate-mapping>
小結:
從上面的單向和雙向映射關系以及分别對應的主鍵和外鍵兩種映射,可以發現外鍵映射隻需要在存在外鍵的表中使用
<many-to-one>标簽,因為唯一是以要添加unique屬性。
<one-to-one>标簽表明了一種一對一的關系,隻是表明一個對象如何加載另一個對象并不在關系模型中添加新列。
主鍵使用<one-to-one>不會生成屬性列,必須對表的主鍵采用foreign的主鍵生成政策,必須表明外鍵對象。
外鍵映射需要采用<many-to-one>生成外鍵列。