[ SSH框架 ] Hibernate框架學習之三


一、表關系的分析

  Hibernate框架實現了ORM的思想,將關系數據庫中表的數據映射成對象,使開發人員把對數據庫的操作轉化為對對象的操作,Hibernate的關聯關系映射主要包括多表的映射配置、數據的增加、刪除等。
  數據庫中多表之間存在着三種關系,也就是系統設計中的三種實體關系。如圖所示。

   

  從圖可以看出,系統設計的三種實體關系分別為:多對多、一對多和一對一關系。在數據庫中實體表之間的關系映射是采用外鍵來描述的,具體如下。

1.1 表與表的三種關系
●  一對多
建表原則:再多的一方創建外鍵指向一的一方的主鍵:
 
●  多對多
建表原則:創建一個中間表,中間表中至少兩個字段作為外鍵分別指向多對多雙方的主鍵
 
●  一對一
建表原則(兩種):①  唯一外鍵對應:假設一對一中的任意一方為多,在多的一方創建外鍵指向一的一方的主鍵,然后將外鍵設置為唯一。
            ②  主鍵對應:一方的主鍵作為另一方的主鍵。

 

   數據庫表能夠描述的實體數據之間的關系,通過對象也可以進行描述,所謂的關聯映射就是將關聯關系映射到數據庫里,在對象模型中就是一個或多個引用。在 Hibernate中采用Java對象關系來描述數據表之間的關系,具體如圖所示。
      
  從圖可以看出,通過一對一的關系就是在本類中定義對方類型的對象,如A中定義B類類型的
屬性b,B類中定義A類類型的屬性a:一對對多的關系,圖中描述的是一個A對應多個B類類型的
情況,需要在A類以Set集合的方式引入B類型的對象,在B類中定義A類類型的屬性a;多對多
的關系,在A類中定義B類類型的Set集合,在B類中定義A類類型的Set集合,這里用Set集合
的目的是避免了數據的重復。
  以上就是系統模型中實體設計的三種關聯關系,由於一對一的關聯關系在開發中不常使用,所以我們不單獨講解,了解即可。那么接下來我們就先來學習一下一對多的關系映射。
 
二、Hibernate 一對多關系映射
 
2.1創建表
 

聯系人表中存在外鍵(lkm_cust_id),外鍵指向客戶表,表示如下圖:

2.2 創建實體:

客戶實體: 

package com.Kevin.domain;
/**
 * 創建客戶實體類
 *  
 */

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

public class Customer implements Serializable {
    private Long cust_id;
    private String cust_name;
    private String cust_address;    
    private String cust_source;
    private String cust_industry;
    private String cust_level;
    private String cust_phone;
    private String cust_mobile;
    
    private Set<Linkman> linkmans=new HashSet<Linkman>(0);
    
    //一對多關系映射:多的一方
    //主表實體應該包含從表實體的集合引用
    public Set<Linkman> getLinkmans() {
        return linkmans;
    }
    public void setLinkmans(Set<Linkman> linkmans) {
        this.linkmans = linkmans;
    }
    public Long getCust_id() {
        return cust_id;
    }
    public void setCust_id(Long cust_id) {
        this.cust_id = cust_id;
    }
    public String getCust_address() {
        return cust_address;
    }
    public void setCust_address(String cust_address) {
        this.cust_address = cust_address;
    }
    public String getCust_name() {
        return cust_name;
    }
    public void setCust_name(String cust_name) {
        this.cust_name = cust_name;
    }
    public String getCust_source() {
        return cust_source;
    }
    public void setCust_source(String cust_source) {
        this.cust_source = cust_source;
    }
    public String getCust_industry() {
        return cust_industry;
    }
    public void setCust_industry(String cust_industry) {
        this.cust_industry = cust_industry;
    }
    public String getCust_level() {
        return cust_level;
    }
    public void setCust_level(String cust_level) {
        this.cust_level = cust_level;
    }
    public String getCust_phone() {
        return cust_phone;
    }
    public void setCust_phone(String cust_phone) {
        this.cust_phone = cust_phone;
    }
    public String getCust_mobile() {
        return cust_mobile;
    }
    public void setCust_mobile(String cust_mobile) {
        this.cust_mobile = cust_mobile;
    }
    @Override
    public String toString() {
        return "Customer [cust_id=" + cust_id + ", cust_address=" + cust_address + ", cust_name=" + cust_name
                + ", cust_source=" + cust_source + ", cust_industry=" + cust_industry + ", cust_level=" + cust_level
                + ", cust_phone=" + cust_phone + ", cust_mobile=" + cust_mobile + "]";
    }
    
    

}

聯系人實體:

package com.Kevin.domain;
/**
 * 創建聯系人實體類
 *  
 */
import java.io.Serializable;

public class Linkman implements Serializable {
    private Long lkm_id;
    private String lkm_name;
    private String lkm_gender;
    private String lkm_mobile;
    private String lkm_phone;
    private String lkm_email;
    private String lkm_qq;
    private String lkm_position;
    private String lkm_memo;
    
    //一對多關系影射
    //從表實體包含主表實體的對象引用
    private Customer customer;
    
    
    public Customer getCustomer() {
        return customer;
    }
    public void setCustomer(Customer customer) {
        this.customer = customer;
    }
    public Long getLkm_id() {
        return lkm_id;
    }
    public void setLkm_id(Long lkm_id) {
        this.lkm_id = lkm_id;
    }
    public String getLkm_name() {
        return lkm_name;
    }
    public void setLkm_name(String lkm_name) {
        this.lkm_name = lkm_name;
    }
    public String getLkm_gender() {
        return lkm_gender;
    }
    public void setLkm_gender(String lkm_gender) {
        this.lkm_gender = lkm_gender;
    }
    public String getLkm_mobile() {
        return lkm_mobile;
    }
    public void setLkm_mobile(String lkm_mobile) {
        this.lkm_mobile = lkm_mobile;
    }
    public String getLkm_phone() {
        return lkm_phone;
    }
    public void setLkm_phone(String lkm_phone) {
        this.lkm_phone = lkm_phone;
    }
    public String getLkm_email() {
        return lkm_email;
    }
    public void setLkm_email(String lkm_email) {
        this.lkm_email = lkm_email;
    }
    public String getLkm_qq() {
        return lkm_qq;
    }
    public void setLkm_qq(String lkm_qq) {
        this.lkm_qq = lkm_qq;
    }
    public String getLkm_position() {
        return lkm_position;
    }
    public void setLkm_position(String lkm_position) {
        this.lkm_position = lkm_position;
    }
    public String getLkm_memo() {
        return lkm_memo;
    }
    public void setLkm_memo(String lkm_memo) {
        this.lkm_memo = lkm_memo;
    }
    @Override
    public String toString() {
        return "Linkman [lkm_id=" + lkm_id + ", lkm_name=" + lkm_name + ", lkm_gender=" + lkm_gender + ", lkm_mobile="
                + lkm_mobile + ", lkm_phone=" + lkm_phone + ", lkm_email=" + lkm_email + ", lkm_qq=" + lkm_qq
                + ", lkm_position=" + lkm_position + ", lkm_memo=" + lkm_memo + "]";
    }
    
    

}

 

2.3 創建映射

客戶映射:

<?xml version="1.0" encoding="UTF-8"?>
<!-- 
創建客戶類關系映射
導入dtd約束
 -->
 <!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- 
    private Long cust_id;
    private String cust_address;
    private String cust_name;
    private String cust_source;
    private String cust_industry;
    private String cust_level;
    private String cust_phone;
    private String cust_mobile;
 -->    
<hibernate-mapping package="com.Kevin.domain">
    <class name="Customer" table="cust_customer" lazy="false">
        <id name="cust_id">
            <generator class="native"></generator>
        </id>
        <property name="cust_name" column="cust_name"></property>
        <property name="cust_address" column="cust_address"></property>
        <property name="cust_source" column="cust_source"></property>
        <property name="cust_industry" column="cust_industry"></property>
        <property name="cust_level" column="cust_level"></property>
        <property name="cust_phone" column="cust_phone"></property>
        <property name="cust_mobile" column="cust_mobile"></property>
        
        <!-- 一對多關系影射:主表實體的映射配置
            涉及的標簽:set:用於配置set集合屬性
                            屬性:name:指定實體類中set集合的屬性名稱
                                  table:指定從表的名稱,在一對多配置時可以不寫
                        key:用於映射外鍵字段
                            屬性:column:指定外鍵字段名稱
                        one—to—many:用於建立一對多的映射配置
                            屬性:class:指定從表實體類的名稱                  
         -->
        <set name="linkmans" table="cust_linkman" >
            <key column="lkm_cust_id"></key>
            <one-to-many class="Linkman"/>
        </set>
    </class>
</hibernate-mapping>
   使用set集合來描述 Customer.java類中的屬性 linkman。在 Hibernate的映射文件中,使用<set>標簽用來描述被映射類中的Set集合,<key>標簽的 column 屬性值對應文件多的一方的外鍵名稱,在 Customer.java客戶類中,客戶與聯系人是一對多的關系,,Hibernate的映射文件中,使用< one-to-many>標簽來描述持久化類的一對多關聯,其中 class屬性用來描述映射的關聯類。

聯系人映射:

<?xml version="1.0" encoding="UTF-8"?>
<!-- 
創建聯系人實體類映射
導入dtd約束
 -->
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    
<!-- 
    private Long lkm_id;
    private String lkm_name;
    private String lkm_gender;
    private String lkm_mobile;
    private String lkm_phone;
    private String lkm_email;
    private String lkm_qq;
    private String lkm_position;
    private String lkm_memo;
 --> 
<hibernate-mapping package="com.Kevin.domain">
    <class name="Linkman" table="cust_linkman">
        <id name="lkm_id">
            <generator class="native"></generator>
        </id>
        <property name="lkm_name" column="lkm_name"></property>
        <property name="lkm_gender" column="lkm_gender"></property>
        <property name="lkm_mobile" column="lkm_mobile"></property>
        <property name="lkm_phone" column="lkm_phone"></property>
        <property name="lkm_email" column="lkm_email"></property>
        <property name="lkm_qq" column="lkm_qq"></property>
        <property name="lkm_position" column="lkm_position"></property>
        <property name="lkm_memo" column="lkm_memo"></property>
        
        <!-- 一對多關系影射:從表實體的映射配置
            涉及的標簽:many-to-one:建立多對一的映射配置
                                屬性:name:從表示實體中引用主表實體對象的引用的名稱
                                      class:指定屬性所對應的實體類名稱        
         -->
        <many-to-one name="customer" class="Customer" column="lkm_cust_id" ></many-to-one>
    </class>
</hibernate-mapping> 
  <many-to-one>標簽定義兩個持久化類的關聯,這種關聯是數據表間的多對一關聯,聯系人與客戶就是多對一的關系,所以用< many-to-one>標簽來描述。<many-to-one>標簽的name屬性用來描述
customer在 Linkman.java類中的屬性的名稱,class屬性用來指定映射的類,column屬性值對應表中的外鍵列名。

2.4 將映射添加到配置文件
        <mapping resource="com/Kevin/domain/Linkman.hbm.xml"/>
        <mapping resource="com/Kevin/domain/Customer.hbm.xml"/>

 

2.5 編寫測試代碼

  @Test
    public void test2(){
        Session s=HibernateUtil.getCurrSession();
        Transaction tx=s.beginTransaction();
        
        //1.創建一個客戶
        Customer c1=new Customer();   //瞬時態
        c1.setCust_name("Kevin_one2many");
        //2.創建一個新的聯系人
        Linkman lkm1=new Linkman();   //瞬時態
        lkm1.setLkm_name("Kevin_one2many1");
        Linkman lkm2=new Linkman();   //瞬時態
        lkm2.setLkm_name("Kevin_one2many2");
        //3.建立客戶和聯系人的關聯關系(讓雙向)
        lkm1.setCustomer(c1);
        lkm2.setCustomer(c1);
        c1.getLinkmans().add(lkm1);
        c1.getLinkmans().add(lkm2);
        //4.保存要符合原則
        s.save(c1);         //持久態 有一級緩存和快照
        s.save(lkm1);    //持久態 有一級緩存和快照
        s.save(lkm2);
        tx.commit();
    }

  在配置文件中添加了自動建表信息后,運行程序時,程序會自動創建兩張表,並且插入數據。運行方法后,控制台輸出結果如所示:

   從圖的輸出結果可以看到,控制台成功輸出了三條insert語句和兩條update語句,此時查詢數據庫中的數據如圖所示:

  從上圖的查詢結果可以看出,數據表創建成功,並成功插入了相應的數據。那么一個基本的一對多的關聯關系映射就已經配置好了。從以上代碼我們可以發現我們建立的關系是雙向的,即客戶關聯了聯系人,同時聯系人也關聯了客戶。

 

三、一對多的相關操作

  級聯操作是指當主控方執行保存、更新或者刪除操作時,其關聯對象(被控方)也執行相同的操作。在映射文件中通過對 cascade屬性的設置來控制是否對關聯對象采用級聯操作,級聯操作對各種關聯關系都是有效的。

3.1 級聯保存或更新

   級聯是有方向性的,所謂的方向性指的是,在保存一的一方級聯多的一方和在保存多的一方級聯一的一方。
保存客戶級聯聯系人
  首先要確定我們要保存的主控方是那一方,我們要保存客戶,所以客戶是主控方,那么需要在客戶的映射文件中進行如下的配置。
<!-- 一對多關系影射:主表實體的映射配置
            涉及的標簽:set:用於配置set集合屬性
                            屬性:name:指定實體類中set集合的屬性名稱
                                  table:指定從表的名稱,在一對多配置時可以不寫
                        key:用於映射外鍵字段
                            屬性:column:指定外鍵字段名稱
                        one—to—many:用於建立一對多的映射配置
                            屬性:class:指定從表實體類的名稱        
                                
         -->
        <set name="linkmans" table="cust_linkman" cascade="save-update">
            <key column="lkm_cust_id"></key>
            <one-to-many class="Linkman"/>
        </set>

然后可以編寫如下測試代碼:

@Test
    public void test(){
        Session s=HibernateUtil.getCurrSession();
        Transaction tx=s.beginTransaction();
        
        //1.創建一個客戶
        Customer c1=new Customer();   //瞬時態
        c1.setCust_name("Kevin");
        //2.創建一個新的聯系人
        Linkman lkm1=new Linkman();   //瞬時態
        lkm1.setLkm_name("Kevin_one2many");
        //3.建立客戶和聯系人的關聯關系(讓雙向)
        lkm1.setCustomer(c1);
        c1.getLinkmans().add(lkm1);
        //4.保存要符合原則
        s.save(c1);         //持久態 有一級緩存和快照
        tx.commit();
    }

保存聯系人級聯客戶

  同樣我們需要確定主控方,現在我們的主控方是聯系人。所以需要在聯系人的映射文件中進行配置,內容如下:

<!-- 一對多關系影射:從表實體的映射配置
            涉及的標簽:many-to-one:建立多對一的映射配置
                                屬性:name:從表示實體中引用主表實體對象的引用的名稱
                                      class:指定屬性所對應的實體類名稱                                         
 -->
 <many-to-one name="customer" class="Customer" column="lkm_cust_id" cascade="save-update"></many-to-one>

編寫如下測試代碼:

@Test
    public void test(){
        Session s=HibernateUtil.getCurrSession();
        Transaction tx=s.beginTransaction();
        
        //1.創建一個客戶
        Customer c1=new Customer();   //瞬時態
        c1.setCust_name("Kevin");
        //2.創建一個新的聯系人
        Linkman lkm1=new Linkman();   //瞬時態
        lkm1.setLkm_name("Kevin_one2many");
        //3.建立客戶和聯系人的關聯關系(讓雙向)
        lkm1.setCustomer(c1);
        c1.getLinkmans().add(lkm1);
        //4.保存要符合原則
        s.save(lkm1);         //持久態 有一級緩存和快照
        tx.commit();
    }

 

3.2 級聯更新

    @Test
    public void test5(){
        Session s=HibernateUtil.getCurrSession();
        Transaction tx=s.beginTransaction();
        
        //1.查詢一個客戶
        Customer c1=s.get(Customer.class, 1l);
        //2.創建一個新的聯系人
        Linkman lkm=new Linkman(); //瞬時態
        lkm.setLkm_name("one2many_update");
        //3.建立客戶和聯系人的關聯關系(雙向)
        lkm.setCustomer(c1);
        c1.getLinkmans().add(lkm);
        //4.更新聯系人
        s.update(c1);
        tx.commit();
    }

 

3.3 Hibernate 的級聯刪除
   我們之前學習過級聯保存或更新,那么再來看級聯刪除也就不難理解了,級聯刪除也是有方向性的,刪刪除客戶同時級聯刪除聯系人,也可以刪除聯系人同時級聯刪除客戶(這種需求很少)。
  原來JDBC中刪除客戶和聯系人的時候,如果有外鍵的關系是不可以刪除的,但是現在我們使用了 Hibernate,其實 Hibernate可以實現這樣的功能,但是不會刪除客戶同時刪除聯系人,默認情況下 Hibernate會怎么做呢呢?我們們來看下面的測試:
    @Test 
    public void test6(){
        Session s=HibernateUtil.getCurrSession();
        Transaction tx =s.beginTransaction();
        
        Customer c=s.get(Customer.class, 71);
        //刪除客戶
        s.delete(c);
        tx.commit();
    }
默認的情況下如果客戶下面還有聯系人,,Hibernate會將聯系人的外鍵置為null,然后去刪除客戶。那么其實有的時候我們需要刪除客戶的時候,同時將客戶關聯的聯系人一並刪除。這個時候我們就需要使用 Hibernate的級聯保存操作了。
刪除客戶的時候同時刪除客戶的聯系人
確定刪除的主控方式客戶,所以需要在客戶端配置:
        <set name="linkmans" table="cust_linkman" cascade="save-update,delete">
            <key column="lkm_cust_id"></key>
            <one-to-many class="Linkman"/>
        </set>

編寫如下測試代碼:

    @Test 
    public void test6(){
        Session s=HibernateUtil.getCurrSession();
        Transaction tx =s.beginTransaction();
        
        Customer c=s.get(Customer.class, 7l);
        //刪除客戶
        s.delete(c);
        tx.commit();
    }
 
3.4 雙向關聯產生多余的SQL語句
  之前已經分析過了,因為雙向維護了關系,而且持久態對象可以自動更新數據庫,更新客戶的時候會修改一次外鍵,更新聯系人的時候同樣也會修改一次外鍵。這樣就會產生了多余的SQL語句,那么問題產生了,我們又該如何解決呢?其實解決的辦法很簡單,只需要將一方放棄外鍵維護權即可。也就是說關系不是雙方維護的,只需要交給某一方去維護就可以了。通常我們都是交給多的一方去維護的。為什么呢?因為多的方才是維護關系的最好的地方。舉個例子,一個老師對應多個學生,一個學生對應一個老師,這是典型的一對多。那么一個老師如果要記住所有學生的名字很難的,但如果讓每個學生記住老師的名字應該不難。其實就是這個道理。所以在一對多中,一的一方都會放棄外鍵的維護權(關系的維護)。
  這個時候如果想讓一的一方放棄外鍵的維護權,只需要進行如下的配置即可。

  inverse的默認值是false ,代表不放棄外鍵維護權,配置值為true,代表放棄了外鍵的維護權。此時就不會再產生之前的問題。

 

四、Hibernate的多對多關聯關系映射

4.1 創建表

數據模型如下:

4.2 創建實體

 用戶實體:

package com.Kevin.domain;
/**
 * 用戶實體類
 */

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

public class SysUser implements Serializable {
    private Long userId;
    private String userName;
    private String userPassword;
    private Integer userState;
    //多對多關系映射:
    private Set<SysRole> roles=new HashSet<SysRole>(0);
    
    public Set<SysRole> getRoles() {
        return roles;
    }
    public void setRoles(Set<SysRole> roles) {
        this.roles = roles;
    }
    public Long getUserId() {
        return userId;
    }
    public void setUserId(Long userId) {
        this.userId = userId;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public String getUserPassword() {
        return userPassword;
    }
    public void setUserPassword(String userPassword) {
        this.userPassword = userPassword;
    }
    public Integer getUserState() {
        return userState;
    }
    public void setUserState(Integer userState) {
        this.userState = userState;
    }
    @Override
    public String toString() {
        return "SysUser [userId=" + userId + ", userName=" + userName + ", userPassword=" + userPassword
                + ", userState=" + userState + "]";
    }
    

}

角色實體:

package com.Kevin.domain;
/**
 * 角色的實體類
 */

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

public class SysRole implements Serializable {
    private Long roleId;
    private String roleName;
    private String roleMemo;
    //多對多關系映射:一個角色可以賦予多個用戶
    private Set<SysUser> users=new HashSet<SysUser>(0);
    
    public Set<SysUser> getUsers() {
        return users;
    }
    public void setUsers(Set<SysUser> users) {
        this.users = users;
    }
    public Long getRoleId() {
        return roleId;
    }
    public void setRoleId(Long roleId) {
        this.roleId = roleId;
    }
    public String getRoleName() {
        return roleName;
    }
    public void setRoleName(String roleName) {
        this.roleName = roleName;
    }
    public String getRoleMemo() {
        return roleMemo;
    }
    public void setRoleMemo(String roleMemo) {
        this.roleMemo = roleMemo;
    }
    @Override
    public String toString() {
        return "SysRole [roleId=" + roleId + ", roleName=" + roleName + ", roleMemo=" + roleMemo + "]";
    }
    

}

 

4.3 創建映射

用戶映射:

<?xml version="1.0" encoding="UTF-8"?>
<!-- 
創建用戶類關系映射
導入dtd約束
 -->
 <!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- 
    private Long userId;
    private String userName;
    private String userPassword;
    private Integer userState;
 -->    
<hibernate-mapping package="com.Kevin.domain">
    <class name="SysUser" table="sys_user" >
        <id name="userId" column="user_id">
            <generator class="native"></generator>
        </id>
        <property name="userName" column="user_name"></property>
        <property name="userPassword" column="user_password"></property>
        <property name="userState" column="user_state"></property>
        <!-- 
            多對多關系映射涉及的標簽:
                set:用於映射set集合屬性
                    name:指定集合名稱
                    table:指定中間表的名稱
                key:用於映射外鍵字段
                    column:指定當前實體在中間表的外鍵字段名稱
                many-to-many:用於映射多對多的關系
                    class:對方的實體類
                    column:    對方在中間類的外鍵字段名稱
         -->
         <set name="roles" table="user_role_ref" inverse="true" cascade="delete">
             <key column="user_id"></key>
             <many-to-many class="SysRole" column="role_id" />
         </set>
    </class>
</hibernate-mapping>

角色映射:

<?xml version="1.0" encoding="UTF-8"?>
<!-- 
創建用戶類關系映射
導入dtd約束
 -->
 <!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- 
    private Long roleId;
    private String roleName;
    private String roleMemo;
 -->    
<hibernate-mapping package="com.Kevin.domain">
    <class name="SysRole" table="sys_role" >
        <id name="roleId" column="role_id">
            <generator class="native"></generator>
        </id>
        <property name="roleName" column="role_name"></property>
        <property name="roleMemo" column="role_memo"></property>
                <!-- 
            多對多關系映射涉及的標簽:
                set:用於映射set集合屬性
                    name:指定集合名稱
                    table:指定中間表的名稱
                key:用於映射外鍵字段
                    column:指定當前實體在中間表的外鍵字段名稱
                many-to-many:用於映射多對多的關系
                    class:對方的實體類
                    column:    對方在中間類的外鍵字段名稱
         -->
         <set name="users" table="user_role_ref" cascade="delete">
             <key column="role_id"></key>
             <many-to-many class="SysUser" column="user_id"/>
         </set>
    </class>
</hibernate-mapping>

4.4 在核心配置中加入映射文件

        <mapping resource="com/Kevin/domain/SysUser.hbm.xml"/>
        <mapping resource="com/Kevin/domain/SysRole.hbm.xml"/>

4.5 編寫測試類

    /**
     * 保存操作:需求:創建2個用戶和3個角色
     *                     讓1號用戶具備1號和2號角色
     *                     讓2號用戶具備2號和3號角色
     *                     保存用戶和角色
     */
    @Test
    public void test(){
        SysUser u1=new SysUser();
        u1.setUserName("User1");
        SysUser u2=new SysUser();
        u2.setUserName("User2");
        
        SysRole r1=new SysRole();
        r1.setRoleName("Role1");
        SysRole r2=new SysRole();
        r2.setRoleName("Role2");
        SysRole r3=new SysRole();
        r3.setRoleName("Role3");
        
        //建立雙相關聯關系
        //先建立用戶
        u1.getRoles().add(r1);
        u1.getRoles().add(r2);
        u2.getRoles().add(r2);
        u2.getRoles().add(r3);
        //建立角色
        r1.getUsers().add(u1);
        r2.getUsers().add(u1);
        r2.getUsers().add(u2);
        r3.getUsers().add(u2);
        
        Session s=HibernateUtil.getCurrSession();
        Transaction tx=s.beginTransaction();
        
        s.save(u1);
        s.save(u2);
        s.save(r1);
        s.save(r2);
        s.save(r3);
        tx.commit();
    }

 

五、多對多的相關操作

5.1 級聯保存或更新

  之前已經學習過一對多的級聯保存了,那么多對多也是一樣的。如果只保存單獨的一方是不可以的,還是需要保存雙方的。如果就想保存一方就需要設置級聯操作。同樣要看保存的主控方是哪一端,就需要在那一端進行配置。

保存用戶級聯角色

   

 

編寫測試代碼:

/**
     * 級聯保存操作:
     * 需求:創建2個用戶和3個角色
     *                     讓1號用戶具備1號和2號角色
     *                     讓2號用戶具備2號和3號角色
     *                     保存用戶和角色
     */
    @Test
    public void test1(){
        SysUser u1=new SysUser();
        u1.setUserName("User1");
        SysUser u2=new SysUser();
        u2.setUserName("User2");
        
        SysRole r1=new SysRole();
        r1.setRoleName("Role1");
        SysRole r2=new SysRole();
        r2.setRoleName("Role2");
        SysRole r3=new SysRole();
        r3.setRoleName("Role3");
        
        //建立雙相關聯關系
        //先建立用戶
        u1.getRoles().add(r1);
        u1.getRoles().add(r2);
        u2.getRoles().add(r2);
        u2.getRoles().add(r3);
        //建立角色
        r1.getUsers().add(u1);
        r2.getUsers().add(u1);
        r2.getUsers().add(u2);
        r3.getUsers().add(u2);
        
        Session s=HibernateUtil.getCurrSession();
        Transaction tx=s.beginTransaction();
        
        s.save(u1);
        s.save(u2);
        tx.commit();
    }

 保存角色級聯用戶

 

編寫測試代碼:

/**
     * 級聯保存操作:保存角色級聯用戶
     * 需求:創建2個用戶和3個角色
     *                     讓1號用戶具備1號和2號角色
     *                     讓2號用戶具備2號和3號角色
     *                     保存用戶和角色
     */
    @Test
    public void test3(){
        SysUser u1=new SysUser();
        u1.setUserName("User1");
        SysUser u2=new SysUser();
        u2.setUserName("User2");
        
        SysRole r1=new SysRole();
        r1.setRoleName("Role1");
        SysRole r2=new SysRole();
        r2.setRoleName("Role2");
        SysRole r3=new SysRole();
        r3.setRoleName("Role3");
        
        //建立雙相關聯關系
        //先建立用戶
        u1.getRoles().add(r1);
        u1.getRoles().add(r2);
        u2.getRoles().add(r2);
        u2.getRoles().add(r3);
        //建立角色
        r1.getUsers().add(u1);
        r2.getUsers().add(u1);
        r2.getUsers().add(u2);
        r3.getUsers().add(u2);
        
        Session s=HibernateUtil.getCurrSession();
        Transaction tx=s.beginTransaction();
        s.save(r1);
        s.save(r2);
        s.save(r3);
        tx.commit();
    }

 

5.2 級聯刪除(了解)

   級聯刪除僅作了解,因為在實際開發中是禁止用的。由於在多對多關聯關系下,往往有多個對象是關聯的,因此只要刪除一個,使用級聯操作,就會刪除多個對象和數據。

 

測試代碼:

    /**
     * 刪除操作
     * 在實際開發中:多對多的雙向級聯刪除是禁止使用的
     */
    @Test
    public void test2(){
        Session s=HibernateUtil.getCurrSession();
        Transaction tx=s.beginTransaction();
        
        SysUser u1=s.get(SysUser.class, 1l);
        
        s.delete(u1);
        tx.commit();
    }

 

 

我的博客即將搬運同步至騰訊雲+社區,邀請大家一同入駐:https://cloud.tencent.com/developer/support-plan?invite_code=3gy4lgwd4jqc4


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM