天天看點

hibernate關系映射之單向多對一和雙向一對多雙向多對一關系——在元映射中添加如下屬性單向一對多關系:

建立域模型和關系資料模型有着不同的出發點:

—域模型: 由程式代碼組成, 通過細化持久化類的的粒度可提高代碼的可重用性, 簡化程式設計

—在沒有資料備援的情況下, 應該盡可能減少表的數目, 簡化表之間的參照關系, 以便提高資料的通路速度

Hibernate 把持久化類的屬性分為兩種:

 值(value)類型(pay): 沒有 OID, 不能被單獨持久化, 生命周期依賴于所屬的持久化類的對象的生命周期。

 實體(entity)類型(worker): 有 OID, 可以被單獨持久化, 有獨立的生命周期顯然無法直接用 property 映射 pay 屬性。

 Hibernate 使用 <component> 元素來映射組成關系, 該元素表名 pay 屬性是 Worker 類一個組成部分, 在 Hibernate 中稱之為元件。

  <!-- 映射組成關系 -->

        <component name="pay" class="Pay">

        <parent name="worker"/>

        <!-- 指定組成關系的元件的屬性 -->

        <property name="monthlyPay" column="MONTHLY_PAY"></property>

        <property name="yearPay" column="YEAR_PAY"></property>

        <property name="vocationWithPay" column="VOCATION_WITH_PAY"></property>

        </component>

雙向多對一關系——在元映射中添加如下屬性

并且在實體類中互相添加相關屬性元素

如:n端添加private Customer customer;當然也得添加必要的setter或getter方法。

      1端添加

private Java.util.Set<Order> orders = new HashSet<>();

<!-- 映射 1 對多的那個集合屬性 -->

        <!-- set: 映射 set 類型的屬性, table: set 中的元素對應的記錄放在哪一個資料表中. 該值需要和多對一的多的那個表的名字一緻 -->

        <!-- inverse: 指定由哪一方來維護關聯關系. 通常設定為 true, 以指定由多的一端來維護關聯關系 -->

        <!-- cascade 設定級聯操作. 開發時不建議設定該屬性. 建議使用手工的方式來處理 -->

        <!-- order-by 在查詢時對集合中的元素進行排序, order-by 中使用的是表的字段名, 而不是持久化類的屬性名  -->

        <set name="orders" table="ORDERS" inverse="true" order-by="ORDER_NAME DESC">cascade=“delete”或save-update或all或all-delete-orphan或delete-orphan

        <!-- 執行多的表中的外鍵列的名字 -->

        <key column="CUSTOMER_ID"></key>

        <!-- 指定映射類型 -->

        <one-to-many class="Order"/>

        </set>

@Test

public void testDelete(){

//在不設定級聯關系的情況下, 且 1 這一端的對象有 n 的對象在引用, 不能直接删除 1 這一端的對象

//Customer customer = (Customer) session.get(Customer.class, 1);

//session.delete(customer); 

}

@Test

public void testUpdat2(){

Customer customer = (Customer) session.get(Customer.class, 1);

customer.getOrders().iterator().next().setOrderName("GrG"); 

}

@Test

public void testUpdate(){

Order order = (Order) session.get(Order.class, 1);

order.getCustomer().setCustomerName("FS");

}

@Test

public void testOne2ManyGet(){

//1. 對 n 的一端的集合使用延遲加載

Customer customer = (Customer) session.get(Customer.class, 1);

System.out.println(customer.getCustomerName()); 

//2. 傳回的多的一端的集合時 Hibernate 内置的集合類型. 

//該類型具有延遲加載和存放代理對象的功能. lazy=“proxy”

System.out.println(customer.getOrders().getClass()); 

//session.close();

//3. 可能會抛出 LazyInitializationException 異常 ,在連結關閉的時候

System.out.println(customer.getOrders().size()); 

//4. 再需要使用集合中元素的時候進行初始化. 

}

單向一對多關系:

需要在一的那一端加入多的屬性比如order中加入Customer類的屬性值。

<!-- 

映射多對一的關聯關系。 使用 many-to-one 來映射多對一的關聯關系 

name: 多這一端關聯的一那一端的屬性的名字

class: 一那一端的屬性對應的類名

column: 一那一端在多的一端對應的資料表中的外鍵的名字

-->

<many-to-one name="customer" class="Customer" column="CUSTOMER_ID"></many-to-one>

@Test

public void testMany2OneGet(){

//1. 若查詢多的一端的一個對象, 則預設情況下, 隻查詢了多的一端的對象. 而沒有查詢關聯的

//1 的那一端的對象!

Order order = (Order) session.get(Order.class, 1);

System.out.println(order.getOrderName()); 

System.out.println(order.getCustomer().getClass().getName());

session.close();

//2. 在需要使用到關聯的對象時, 才發送對應的 SQL 語句. 

Customer customer = order.getCustomer();

System.out.println(customer.getCustomerName()); 

//3. 在查詢 Customer 對象時, 由多的一端導航到 1 的一端時, 

//若此時 session 已被關閉, 則預設情況下

//會發生 LazyInitializationException 異常

//4. 擷取 Order 對象時, 預設情況下, 其關聯的 Customer 對象是一個代理對象!

}

繼續閱讀