Hibernate知識點復習之三
阿新 • • 發佈:2018-10-16
hashset mov 時也 其他 多表 系統 系統設計 用戶 hibernate HIbernate知識點復習之三
案例需求描述:
存在著一個客戶對應多個聯系人的情況,單獨在聯系人管理模塊中對聯系人信息進行維護,功能包括:
對聯系人信息進行增刪改查
表關系分析:
一 概述:數據庫中多表之間存在著三種關系:一對一 一對多 多對多 ,這也是系統設計中三種實體關系。
二 建表原則
1 一對多:在多的一方 創建外鍵指向一得一方的主鍵
2 多對多:創建一個中間表,中間表裏創建至少兩個字段作為外鍵,分別指向多對多雙方的主鍵
3 一對一:
(1)主鍵對應:一方主鍵作為另一方主鍵
(2)唯一外鍵:一方創建外鍵字段 指向另一方的主鍵
三Hibernate通過java對象描述數據表的關系:
一 對 一 class A{ class B{ B b; A a; getter和setter方法 getter和setter方法 } } 一 對 多 class A{ class B{ Set<B> b=new HashSet<B>(); A a; getter和setter方法 getter和setter方法 } } 多 對 多 class A{ class B{ Set<B> b;=new HashSet<B>(); Set<A> a=new HashSet<A>(); getter和setter方法 getter和setter方法 } }
多表關系映射配置:
一 一對多配置 1. 一對多的一方: 頭標簽<set name="" cascade="" inverse=""></set> <set>對應著一方實體中關聯多方的set集合屬性,如果是list集合屬性,對應的就是<list> <set>元素的屬性: (1)name(必填) :實體中對應的集合名稱 (2) cascade級聯操作屬性: <1>級聯操作概念:級聯操作是指當主控方執行 保存,更新,刪除操作時,其關聯對象(被控方)也執行相同的操作,簡化操作,少寫代碼 <2>cascade屬性值: * save-update:級聯保存更新 多表操作時,保存一方/主控方(如:客戶)的內容,又更新多方(如:聯系人)的信息 特性:1》只保存一方的問題 2》具有方向性,保存一方同時更新另一方 存在情況:當雙方都設置了save-update,則會雙方都會執行對應關聯的sql語句,從而產生多余sql語句。 * delete:級聯刪除,刪除一方的同時,也刪除多方的信息 概述:使用JDBC刪除客戶和聯系人時,如果有外鍵的關系是不可以刪除的。但Hibernate可以實現這樣的功能。 但使用Hibernate刪除有關聯關系對象(如,客戶)的默認情況,會先將關聯關系的外鍵設置為null,再刪掉客戶對象。 刪除的方式: 1》客戶一方不放棄維護外鍵 inverse="false" ,且沒有設置刪除級聯,屬於默認情況時,若直接刪除客戶則 會把客戶的關聯的外鍵 設置為null再刪。 2》客戶一方不放棄維護外鍵 inverse="false",設置了刪除級聯,若直接刪除客戶,會把客戶關聯的(在另一張表的)聯系人信息也刪掉 3》客戶一方放棄維護外鍵 inverse="true" 時,必須要設置刪除級聯才可進行刪除 * all:save-update + delete (3)inverse:配置關系是否維護 <1>概述:雙向關聯會產生多余的sql語句,如下面的例子 //將2號聯系人關聯的客戶改為2號客戶 Customer customer = session.get(Customer.class,2L); LinkMan linkMan = session.get(LinkMan.class,2L); //雙向關聯 linkMan.setCustomer(customer); customer.getLinkMans().add(linkMan); 此代碼會出現兩個重復(更新外鍵)的update語句, 原因為:進行雙向維護關系時,持久態對象可自動更新到數據庫,更新客戶時會修改一次外鍵, 更新聯系人時也會修改一次外鍵,從而產生多余的sql語句 解決方案:只需一方放棄外鍵維護權即可(inverse="true"),也就是說關系不是雙方維護的,只需交給一方去維護即可 而一對多時,通常由多方進行關系維護(如老師對學生時,每個學生記住一個老師名字容易於一個老師記住全部學生名字) <2>原則:必須要有一方維護關系,如在 一對多關系中,只能是一方 放棄維護關系(inverse="true"),多方不能放棄維護 <3>取值:默認值為false,代表不放棄外鍵維護權,true為放棄外鍵維護權 (4)區分cascade和 inverse: casacde強調的是操作一個對象時,是否還操作其關聯對象 inverse強調的是外鍵的維護權 <set>標簽的子標簽: (1)<key column="" ></key> column對應關聯多方(set方)的數據庫的外鍵名稱 (2)<one-to-many class=""/>class 對應關聯多方的實體全類名 一對多中一方的配置示例: <set name="linkMans" inverse="true" cascade="save-update"> //放棄維護權,級聯保存更新 <key column="lkm_cust_id" /> <one-to-many class="XXXX.ZZZ.LinkMan"/> </set> 2. 一對多的多方: <many-to-one name="customer" column="lkm_cust_id" class="Customer" cascade="save-update"></many-to-one> name:多方實體中關聯對象的屬性名稱 column:關聯實體的在數據庫中對應的外鍵名 class:關聯實體的全類名 cascade:級聯設置 二多對多: 1. 多對多的配置: (1)配置模板: <set name="roles" table="sys_user_role" cascade="save-update"> <key column="user_id"></key> <many-to-many class="xx.xxx.Role" column="role_id"></many-to-many> </set> (2)<set>標簽: name:關聯另一方的集合屬性名稱 table:中間表名稱 (3)<key>標簽: column:當前對象在中間表的外鍵名稱 (4)<many-to-many>標簽: class:關聯另一方的實體全類名 column:關聯另一方對應的外鍵 2. 多對多的外鍵維護問題: (1)概述:在多對多的保存操作中,如果進行雙向關系維護,就必須要有一方放棄外鍵維護權。 原因分析: 因為中間表作為 關系維護紐帶 若兩張表都進行關系維護,則中間表的外鍵錄入每次都不能確定唯一的 主鍵,會出現 2對1的尷尬,會報錯: 解決方案為: 1 不書寫維護雙向關系代碼 2 在某方配置文件中進行 inverse="true"配置 (2)總結: 一般是由被動方放棄,如用戶對角色,角色是被選中,所以角色要放棄外鍵維護權。 但如果進行單向關系維護,就不需任意放棄外鍵維護權。 3. 多對多的級聯配置: 多對多進行保存操作時,不可以保存一方,所以必須要進行保存更新級聯配置(cascade="save-update") 4. 多對多的其他操作: (1)刪除用戶關聯的角色 //查詢2號用戶 User user = session.get(User.class,2L); //查詢1號聯系人 Role role=session.get(Role.class,1L); //操作集合,相當於操作中間表 user.getRoles().remove(role); (2)將某個用戶的角色改選 //查詢2號用戶 User user = session.get(User.class,2L); //查詢1號聯系人 Role role=session.get(Role.class,1L); //查詢2號聯系人 Role role2=session.get(Role.class,2L); //操作集合,相當於操作中間表 user.getRoles().remove(role); user.getRoles().add(role2); (3)給某個用戶添加新角色 //查詢2號用戶 User user = session.get(User.class,2L); //查詢1號聯系人 Role role=session.get(Role.class,1L); //操作集合,相當於操作中間表 user.getRoles().add(role); 一對多 和 多對多配置比較: 一 (Customer) 對 多(LinkMan) private Set<LinkMan>linkMans=new HashSet<LinkMan>(); private Customer customer; <set name="linkMans" inverse="false" cascade="save-update"> <many-to-one name="customer" column="lkm_cust_id" class="Customer" > <key column="lkm_cust_id" /> </many-to-one> <one-to-many class="LinkMan"/> </set> *** 多(User) 對 多(Role) private Set<Role>roles=new HashSet<Role>(); private Set<User>users=new HashSet<User>(); 中間表只有兩個字段:user_id和role_id <set name="roles" table="sys_user_role" cascade="save-update"> <set name="users" table="sys_user_role" inverse="true"> <key column="user_id"></key> <key column="role_id"></key> <many-to-many class="Role" column="role_id"></many-to-many> <many-to-many class="User" column="user_id"></many-to-many> </set> </set>
)
Hibernate知識點復習之三