1、單向N-1
2、單向1-1
3、單向1-N
4、單向N-N
5、雙向1-N
6、雙向N-N
7、雙向1-1
下面就對這七種關聯關係映射進行一個簡單的總結:
一、單向的多對一
看兩個POJO
public class Person{
private int pid;
private String name;
private Address address;
...//產生相應的getter、setter方法
}
----------------------------------------
public class Address{
private int id;
private String detail;
...//產生相應的getter、setter方法
}
這裡我們需要維護的關係是多個Person可以對應同一個地址,使用單向的N-1映射我們只需要在多的一端加入一個外鍵指向一的一端即可
**看設定檔
<class name="Person">
<id name="id">
<generator class="native"/>
</id>
...//部分欄位配置省略
<many-to-one name="address" column="addressId"/>//關鍵配置
</class>
這樣配置以後hibernate就會幫我們在多的一端(Person)添加一個外鍵addressId指向一的一端
二、單向的1-1(外部索引鍵關聯)
可以採用<many-to-one>標籤,指定多的一端的unique=true,這樣就限制了多的一端的多重性唯一
通過這種手段映射一對一唯一外部索引鍵關聯
設定檔只需要修改為:
<many-to-one name="address" column="addressId" unique="true"/>
三、單向的1-N
**看代碼,我們知道一個班級有多名學生,這就是一個典型的1-N關係
public class Classes {
private int id;
private String name;
private Set students;
...//產生相應的getter、setter方法
}
---------------------------------------------------------------------------
public class Student {
private int id;
private String name;
..//產生相應是getter、setter方法
}
**映射原理:一對多關聯映射,在多的一端添加一個外鍵指向一的一端,它維護的關係是一指向多
**設定檔:
<class name="Classes" table="t_classes">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<set name="students">
<key column="classesid"/>//在一的一端添加的外鍵指向多的一端(預設情況下市主鍵匹配)
<one-to-many class="xxx.Student"/>//注意它維護的是一指向多的關係
</set>
</class>
四、雙向1-N
上面提到了單向的1-N在一的一端添加的外鍵指向多的一端即可,對於雙向的1-N則類似於N-N,集合元素中不使用<one-to-many>
元素映射關聯屬性,而使用<many-to-many>元素,但是為了保證一的一端,因此需要增加unique="true"屬性
**配置,簡單修改單向1-N的設定檔
<class name="xxx.Classes" table="t_classes">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<set name="students">
<key column="classesid"/>
<many-to-many class="xxx.Student" unique="true"/>
</set>
</class>
五、單向多對多
**先看兩個POJO
public class User {
private int id;
private String name;
private Set roles;
..//產生相應的getter、setter方法
}
---------------------------------------------------------------------------
public class Role {
private int id;
private String name;
..//產生相應的getter、setter方法
}
現在需要映射這樣的N-N關係,一個User可以有多個Role,而一個Role有可以被多個User所擁有
這樣我們就可以將一個N-N關係拆分為兩個N-1的關係
**看設定檔
<class name="xxx.User" table="t_user">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<set name="roles" table="t_user_role">
<key column="userid"/>
<many-to-many class="xxx.Role" column="roleid"/>
</set>
</class>
這樣我們的關係的明確了
t_user t_user_role t_role
id name < -------userid roleid ----- > id name
六、雙向的多對多關係
雙向的多對多映射需要在兩邊都增加集合元素,用於映射集合屬性
修改上面的單向N-N映射
在Role中添加集合屬性
public class Role {
private int id;
private String name;
privarte Set user
..//產生相應的getter、setter方法
}
修改設定檔
<class name="xxx.User" table="t_user">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<set name="roles" table="t_user_role">
<key column="userid"/>
<many-to-many class="xxx.Role" column="roleid"/>
</set>
</class>
------------------------------------------------------------------------------------------------
<class name="xxx.Role" table="t_role">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<set name="users" table="t_user_role" order-by="userid">
<key column="roleid"/>
<many-to-many class="xxx.User" column="userid"/>
</set>
</class>
注意點:1、雙向多對多關聯兩邊都需要指定串連表的表名和外鍵列的列名
2、兩個集合元素Set的table值必須指定,而且需要相同
七、雙向的一對一關聯
雙向的1-1關聯有兩種形式:
1、基於外鍵的雙向1-1關聯
我們可以回想一下上面提到的單向1-1映射,它是有N-1的一個特例,只需要在<many-to-one>標籤多的一端添加unique="true"屬性就可以形成單向的1-1映射關係,那麼該怎麼樣將這種映射改為雙向的呢?
下面我們再舉個例子:一個User必須要有一個唯一的identityId
首先建立兩個POJO類
public class Person {
private int id;
private String name;
private IdentityId identityId;
..//產生相應的getter、setter方法
}
public class IdentityId {
private int id;
private String cardNo;
private Person person;
..//產生相應的getter、setter方法
}
**看設定檔
<class name="xxx.Person" table="t_person">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<many-to-one name="identityId" class="xxx.IdentityId" unique="true"/>
</class>
-----------------------------------------------------------------------------------
<class name="xxx.IdentityId" table="t_identity">
<id name="id">
<generator class="native"/>
</id>
<property name="cardNo"/>
<one-to-one name="person" class="xxx.Person" property-ref="identityId"/>
</class>
注意:這裡的property-ref屬性為identity表明建立了從identity對象到person對象的關聯.
因此只要調用identity持久化對象的getIdentityId()方法就可以導航到Person對象 由此可見:
Person對象和IdentityId對象之間為雙向的關聯關係person.getIdentityId().getPerson()
2、基於主鍵的1-1雙向關聯
上面的POJO類不需要有任何變化,我們只需要修改設定檔
<class name="xxx.Person" table="t_person">
<id name="id" column="ID">
<generator class="foreign">
<param name="property">identityId</param>
</generator>
</id>
<property name="name"/>
<one-to-one name="identity" clsss="xxx.IdentityId" constrained="true"/>
</class>
注意:這裡的constrained="true"表明Person表的主鍵ID同時作為外鍵參考IdentityId表
--------------------------------------------------------------------------------------
<class name="xxx.Identity" table="t_identity">
<id name="id">
<generator class="native"/>
</id>
<property name="cardNo"/>
<one-to-one name="person" class="xxx.Person"/>
</class>
注意:這裡Person表中ID既是主鍵同時還作為外鍵參照表IdentityId,因為使用了foreign標識符建置原則Hibernate就保證了Person
對象與關聯的IdentityId對象共用一個主鍵
綜上所述,hibernate的實體映射方式很靈活,如果我們使用hibernate映射得當將可以大大簡化持久層資料的訪問!