1. 程式人生 > >Hibernate知識點復習之三

Hibernate知識點復習之三

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知識點復習之三