接下來的這幾篇部落格說的是“實體關系映射”。
一、關系 & 映射
我們先将關系映射,我們拆成“關系”和“映射”兩部分。
關系:不陌生,在“程式員”的概念裡最基本的就是表表之間的關系,類類之間的關系,這裡要說的關系就這兩種。一個系統中的任何一個實體都不是獨立的,這就是我們類圖中各個類之間的互相引用。類圖間的關系表現在資料庫中,就是表之間的的外鍵限制。這些關系有:一對一,一對多,多對一,多對多,繼承。 關系的使用,就涉及到方向的問題,是以,以上幾種關系都有方向存在。
回想之前的設計,step1:類的設計是一部分,形成OOM,拿着oom來生成我們的“代碼”;
step2:資料庫的設計是另一部分,形成PDM,用PDM形成database。
當然都知道利用powerdesigner 等工具,在oom和pdm之間,是可以互相轉換的,程式設計的工作量是大大減輕了,即便這樣,還是有更先進的思想,來解放我們的勞動力,在哪?就是hibernate。
映射:将實體映射到資料庫,基于實體間的關系,這裡的一個“映射”包含了N多種情況,hibernate是怎麼節省工作量的呢?hibernate将之前的兩步,做成了“一步到位”。從代碼開始設計對象,通過“xml”映射到資料庫。hibernate使程式設計更專注于“對象”的設計。那麼系統中“對象”鍵的關系是怎麼“映射”到資料庫中呢?這其中的原理最重要的就是:Hibernate 靠什麼來區分對象間的不同關系?hibernate定義了一套“關系”映射的約定,來區分對象之間的不同關系。這樣我們以前需要手動去維護的資料表外鍵限制,就被hibernate給代勞了。
接下來就看看hibernate中的這套約定。
二、關系規範實作
(這篇部落格說一對一的關系映射的實作)
一對一
有兩種實作方式,主鍵關聯映射,唯一外鍵關聯映射。
約定:one-to-one
1、主鍵關聯映射
實作方式:讓兩個實體的主鍵一樣,這樣就不需要加入多餘的字段了
單向關聯Person----->IdCard
person中存在IdCard的引用,反之沒有,對應的,IdCard.hbm.xml 檔案不會發生變化。需要在person.hbm.xml中加入維護關系的約定内容。
關系圖如下;
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiIXZ05WZD9CX5RXa2Fmcn9CXwczLcVmds92czlGZvwVP9EUTDZ0aRJkSwk0LcxGbpZ2LcBDM08CXlpXazRnbvZ2LcRlMMVDT2EWNvwFdu9mZvwVPFpWT1U0VhRDZtJmdsNjW1ZkMkZXUYpVd1kmYr50MZV3YyI2cKJDT29GRjBjUIF2LcRHelR3LcJzLctmch1mclRXY39DOxYDOzYTNwIzMwETM0EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
實體類實作如下:
<span style="font-family:KaiTi_GB2312;font-size:18px;"> 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;
}
}
</span>
person端的hbm.xml編寫:
<span style="font-family:KaiTi_GB2312;font-size:18px;"> <class name="com.bjpowernode.hibernate.Person" table="t_person">
<id name="id">
<!-- 采用foreign生成政策,forgeign會取得關聯對象的辨別 -->
<generator <strong>class="foreign"</strong>>
<!-- property隻關聯對象 -->
<param name="property">idCard</param>
</generator>
</id>
<property name="name"/>
<strong><one-to-one name="idCard" constrained="true"/></strong>
<!-- one-to-one訓示hibernate如何加載其關聯對象,預設根據主鍵加載也就是拿到關系字段值,根據對端的主鍵來加載關聯對象
constrained="true表示,目前主鍵(person的主鍵)還是一個外鍵參照了對端的主鍵(IdCard的主鍵),也就是會生成外鍵限制語句 -->
</class>
</span>
雙向關聯
在IdCard中加入Person的引用;
在IdCard一段也加入維護關系的約定内容,<one-to-one name="person" />
IdCard配置檔案如下:
<span style="font-family:KaiTi_GB2312;font-size:18px;"> <hibernate-mapping>
<class name="com.bjpowernode.hibernate.IdCard" table="t_idCard">
<id name="id">
<generator class="native"/>
</id>
<property name="cardNo"/>
<strong><one-to-one name="person"/></strong>
</class>
</hibernate-mapping>
</span>
2、唯一外鍵關聯
引入對端實體的主鍵做外鍵限制,來實作,實體都有自己各自的主鍵,不共享主鍵。
約定:<many-to-one> & <one-to-one>
一對一唯一外鍵關聯映射其實是多對一的特例,采用<many-to-one>标簽來映射,指定多的一端unique為true,這樣就限制了多的一端的多重性為一,就是這樣來映射的。
資料表圖:
person的映射檔案如下:
<span style="font-family:KaiTi_GB2312;font-size:18px;"><hibernate-mapping>
<class name="com.bjpowernode.hibernate.Person" table="t_person">
<id name="id">
<generator class="native"/>
</id>
property name="name"/>
<strong><many-to-one name="idCard" unique="true"/></strong>
</class>
</hibernate-mapping></span>
雙向關聯實作——one-to-one
這裡和一對一主鍵關聯的一點小差別是:唯一外鍵關聯在雙向關聯的時候,沒有外鍵的一方是一對一的關系,有外鍵的一方是一對多的關系,是以IdCard使用的是one-to-one
IdCard 映射檔案如下:
<span style="font-family:KaiTi_GB2312;font-size:18px;"><hibernate-mapping>
<class name="com.bjpowernode.hibernate.IdCard" table="t_idCard">
<id name="id">
<generator class="native"/>
</id>
<property name="cardNo"/>
<strong><one-to-one name="person" property-ref="idCard"/></strong>
</class>
</hibernate-mapping>
</span>
兩種方式的對比
一對一主鍵關聯:共用一個主鍵,耦合性太大,雙方關系發生變化,資料庫表就得重建立,不建議使用。
唯一外鍵關聯:增加一個字段,來維護關聯關系,靈活性增加。如雙發關系由一對一向一對多改變的情況下,隻需将限制外鍵的unique設定為false即可實作,建議使用。
下篇部落格是一對多的實作