天天看點

hibernate多表操作詳解

一.簡介

在進行關系型資料庫設計時,表與表之間的關系往往不是獨立的,而是互相關聯的,這就是所謂的多表設計。一般來說,資料庫表與表包含以下幾種關系。

hibernate多表操作詳解

建表原則

一對一:主鍵對應,一方的主鍵作為另一方的主鍵。

一對多:在多的一方建立外鍵指向一的一方的主鍵

多對多:建立一個中間表,中間表的最少兩個字段作為外鍵分别指向多對多雙方的主鍵。

此種關系在hibernate中用Java對象表示如下:

class A				class A					class A
           
B b;				Set<B> bs;				Set<B> bs
	}				}					}
	class B					class B				class B
           
A a;					Set<A> as
		A a;			}					}
	}		
           
一對一的關系			一對多的關系				多對多的關系
           

在一般情況下,一對多的情況是比較常見的,比如學生與老師的關系,部門與員工的關系,客戶與聯系人的關系,是以,下面将以一對多關系為例說明hibernate是怎麼建立多表之間的關系的。

二.hibernate的一對多關系映射操作執行個體

1.例子說明:

本執行個體建立兩個表,分别是聯系人表和客戶表(典型的客戶管理系統中經常遇到的),其中一個客戶擁有多個聯系人,即客戶與聯系人的關系為一對多。是以,聯系人中存在外鍵,該外鍵指向客戶。具體描述如下。

hibernate多表操作詳解

2.建立hibernate實體

聯系人實體

private Long lkm_id;
		private Character lkm_gender;
		private String lkm_name;
		private String lkm_phone;
		private String lkm_email;
		private String lkm_qq;
		private String lkm_mobile;
		private String lkm_memo;
		private String lkm_position;
	
		//注意這裡是關鍵寫法,在多的一方的實體中建立一個類型為一的一方的屬性
		private Customer customer ;
		get方法....
		set方法....
	}
           

客戶實體

public class Customer {
		private Long cust_id;
		private String cust_name;
		private String cust_source;
		private String cust_industry;
		private String cust_level;
		private String cust_linkman;
		private String cust_phone;
		private String cust_mobile;
		//注意這裡是關鍵,在一的一方的實體中建立一個泛型類型為多的一方的set集合。
		private Set<LinkMan> linkMens = new HashSet<LinkMan>();
	}
           

2.建立映射關系

聯系人映射關系的寫法(多的一方)

前面普通字段不再累述,可參見筆者前一篇部落格。重點講述關聯對象的配置。一的一方使用many-to-one元素。

<many-to-one name="customer" column="lkm_cust_id" class="Customer的完整類名"  >
</many-to-one>
           

name屬性:引用屬性名

column屬性: 外鍵列名

class屬性: 與我關聯的對象完整類名

客戶映射關系的寫法(一的一方)

多的一方使用set元素來描述被映射類的set集合,

<set name="linkMens"   >
			<key column="lkm_cust_id" ></key>
			<one-to-many class="LinkMan的完整類名" />
</set>
           

key标簽的column屬性:用來描述對應檔案多的一方的主鍵名稱。

one-to-many元素 的class屬性:用來描述映射關聯類

3.将映射添加到hibernate主配置檔案中

<mapping resource="Customer.hbm.xml檔案的包路徑" />
<mapping resource="LinkMan.hbm.xml的包路徑" />
           

4.編寫測試函數

public void text(){
		//1 獲得session
		Session session = HibernateUtils.openSession();
		//2 開啟事務
		Transaction tx = session.beginTransaction();
		//-------------------------------------------------
		//建立一個客戶
		Customer c = new Customer();
		c.setCust_name("谷歌");
		//建立多個聯系人
		LinkMan lm1 = new LinkMan();
		lm1.setLkm_name("crc");
		LinkMan lm2 = new LinkMan();
		lm2.setLkm_name("psl");
		
		//表達一對多,客戶下有多個聯系人
		c.getLinkMens().add(lm1);
		c.getLinkMens().add(lm2);
		
		//表達對對對,聯系人屬于哪個客戶
		lm1.setCustomer(c);
		lm2.setCustomer(c);
		//若無設定級聯操作,則所有對象均要儲存,否則出現瞬時對象異常。
		session.save(c);
           
session.save(lm1);
		session.save(lm2);
		
		//4送出事務
		tx.commit();
		//5關閉資源
		session.close();
	}
           

若制定Junit測試後為綠條,且資料庫新建立兩個表,說明hibernate執行多表關聯操作成功。

三.hibernate多表關系映射的級聯操作

所謂級聯操作是指當主要方執行儲存,更新,删除操作時,其關聯的對象也會執行相同的操作。在映射檔案中通過set元素的

屬性cascade來配置。主要方的選擇是任意的,但一般習慣主要方選擇為一的一方。

1.級聯儲存,關鍵詞為save-update

配置如下代碼:

<set name="linkMens" cascade="save-update"  >
			<key column="lkm_cust_id" ></key>
			<one-to-many class="LinkMan" />
</set>
           

此時,隻要執行儲存客戶,聯系人會跟着儲存下來。

2.級聯删除,關鍵詞為delete

配置代碼如下

<set name="linkMens"  cascade="delete"  >
			<key column="lkm_cust_id" ></key>
			<one-to-many class="LinkMan" />
</set>
           

這時,在代碼中删除了客戶,與其關聯的聯系人也會跟着删除,但是,要注意,這種操作比較危險,一般不用。

要注意,級聯儲存和級聯删除是可以同時配置 的。

四.雙向關聯産生多餘的SQL語句 的問題

在實行表對象關聯時操作時,SQL語句有可能會重複執行,出現這種問題的原因是,兩個表對象都維護了關系,持久化對象可以自動更新資料庫,更新客戶時會修改一次外鍵,更新聯系人時也會修改一次外鍵,是以産生多餘的SQL語句。解決方法是使其中一方放棄維護關系即可。一般情況下,一的一方放棄維護關系。執行如下配置即可。

<set name="linkMens" inverse="true" cascade="delete,save-update"  >
			<key column="lkm_cust_id" ></key>
			<one-to-many class="LinkMan" />
		</set>
		
           

inverse的預設值為false,代表不放棄外鍵維護權,修改為true,即放棄維護。(注意, 這一點與我們的正常思維相反)

五.總結

資料庫的多表設計問題是一個重要的知識點,本部落格以一對多關系為例,介紹了hibernate中的多表操作。感興趣的朋友可以

深入研究多對多的表關系,或者三表以及更多表的hibernate操作。

繼續閱讀