Hibernate之1-N關聯映射,hibernate1-n映射
一、Hibernate之1-N關聯映射
1. 哪邊是 1 , 哪邊是多 ?
需要從業務的角度來說明。例如,Employee 和 Department 之間就是 n-1 的關聯關係,Order 和 Customer 之間也是 n-1 的關聯關係。
1). 關聯關係是有方向的:
2). 如何在類中來建立關聯關係呢 ? 解:通過成員變數的方式即可.
2. 單向 n-1 關聯關係
1). 域對象中,在 Order 中聲明一個 Customer 類型的成員變數,並提供 setter、getter
public class Order {
private Integer orderId;
private String orderName;
private Customer customer;
//...
}
2). 資料表:
3). 如何進行映射:通過 many-to-one 來映射
①. 注意:需要映射在 ORDERS 資料表中的外鍵列!
<many-to-one name="customer"
column="CUSTOMER_ID"
class="Customer"></many-to-one>
4). API 操作時
①. save 時,若先儲存 Order, 在儲存 Customer,則會多出 UPDATE 語句;若先儲存 Customer,再儲存 Order,則只有 INSERT. 建議先儲存 1 的一端的對象
②. get 時,
◆預設情況下,關聯對象採取 懶載入 策略。即在擷取 Order 時,若不使用關聯的 Customer 的屬性,則不載入 Customer 對象
◆有懶載入就可能會發生懶載入異常:org.hibernate.LazyInitializationException。◇什麼時候出現懶載入異常?擷取一個對象,沒有初始化其關聯的屬性,若在 Session 已經關閉的情況下,訪問關聯的屬性,就會拋出懶載入異常。
③. update 時,
◆若對象本身是一個持久化對象,則在 flush Session 時,會串聯更新其關聯的對象的屬性。
◆若對象是游離對象,則不會更新關聯對象的屬性。但可以通過設定 cascade 屬性來使其能夠進行更新
④. delete 時,
◆刪除對象,只需要 ID 屬性
◆防止發生外鍵約束異常
3. 單向 1-n 關聯關係
1). 域對象:增加集合屬性
public class Customer {
private Integer customerId;
private String customerName;
//訪問 n 的一端的集合屬性
private Set<Order> orders = new HashSet<>();
//....
}
注意:
①. 當 Session 從資料庫中載入 Java 集合時, 建立的是 Hibernate 內建集合類的執行個體,
因此在持久化類中定義集合屬性時必須把屬性聲明為 Java 介面類型
②. 在定義集合屬性時, 通常把它初始化為集合實作類別的一個執行個體.
避免應用程式訪問取值為 null 的集合的方法拋出 NullPointerException
2).關係資料模型
3). 如何進行映射,在Customer.hbm.xml中通過 set 元素
<set name="orders" table="ORDERS"
order-by="ORDER_NAME ASC">
<key column="CUSTOMER_ID"></key>
<one-to-many class="Order"/>
</set>
4). API 具體操作:
①. save 時:因為由 1 的一端來維護關聯關係,所以一定會多出 UPDATE 語句!最好不是有 1 的一端來維護關聯關係
②. update 時:
◆若把集合對象 clear,預設情況下是把多的一端的外鍵置空
③. delete 時:可以刪除 1 的一端,但是把多的一端的外鍵置空
5). set 的 order-by 屬性:可以指定在查詢集合時,按集合元素對應的資料表的列進行排序!
<set name="orders" table="ORDERS"
order-by="ORDER_NAME ASC">
<key column="CUSTOMER_ID"></key>
<one-to-many class="Order"/>
</set>
----------------------------------------------------雙向關聯映射-----------------------------------------------------
4. 雙向 1-n 關聯關係
1). 如何進行映射(下面是Customer表,注意兩者之間的對應關係)
2). set 元素的 inverse 屬性可以指定由哪一方來維護關聯關係,一般地,在雙向 1-n 關聯關係中,1 的一端的 set 的 inverse 都設定為 true,表示有 n 的一端來維護關聯關係!
◆ 比如說在Customer表中:
<set name="orders" table="ORDERS"
order-by="ORDER_NAME ASC" inverse="true">
<key column="CUSTOMER_ID"></key>
<one-to-many class="Order"/>
</set>
hibernate 中 既然1-n的雙向映射 1端不控制關聯關係, 那要這個雙向映射有什用,豈不是與n-1是一樣的?
User {
Set<Order> orders;
}
Order {
User user;
}
一般來說我們讓Order來控制關係。即user的配置<set name="orders" inverse="true">
inverse="true"的意思是,請對方控制關係。也即(User不控制關係,Order控制關係)
即我們修改order.setUser(user),則資料庫會更新。
我們修改user.getOrders().add(order),則資料庫不會更新。
至於怎麼體現雙向,那就是我們從資料庫取user的時候,我們可以直接user.getOrders()
裡面將有我們已經添加的order。
hibernate有幾種映射關係
Hibernate的關聯關係映射大概有這麼幾種:
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......餘下全文>>