JavaWeb - Hibernate框架使用(三)

表與表的關系

關鍵是維護關聯(lián)屬性

一對多|多對一

一對多(多對一):

  • 數(shù)據(jù)表中:

客戶表

cid cname
1 百度
2 網(wǎng)易

? 聯(lián)系人表

lid lname cid
1 張總 1
2 劉總 1
3 王總 2
  • 實體中:

    客戶(Cudtomer)實體:

    private Long cid;
    private String cname;
    //使用集合表達‘一’的一方擁有多個‘多’的一方
    private Set<LinkMan> linkMen;
    

    聯(lián)系人(LinkMan)實體:

    private Long lid;
    private String lname;
    //使用對象引用‘一’的一方表達‘多’的一方屬于哪個‘一’的一方
    private Customer customer;
    
  • orm元數(shù)據(jù)中:

    Customer.hbm.xml中(‘一’的一方):

      <class name="Customer" table="cst_customer" >
          <id name="cust_id"  >
              <generator class="native"></generator>
          </id>
          <property name="cust_name" column="cust_name" ></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_linkman" column="cust_linkman" ></property>
          <property name="cust_phone" column="cust_phone" ></property>
          <property name="cust_mobile" column="cust_mobile" ></property>
      
          <!-- 集合,一對多關系,在配置文件中配置 -->
          <!-- 
              name屬性:集合屬性名
              column屬性: 外鍵列名
              class屬性: 與我關聯(lián)的對象完整類名
           -->
           <!-- 
              級聯(lián)操作:   cascade
                  save-update: 級聯(lián)保存更新
                  delete:級聯(lián)刪除
                  all:save-update+delete
              級聯(lián)操作: 簡化操作.目的就是為了少些兩行代碼.
            -->
            <!-- inverse屬性: 配置關系是否維護. 
                  true: customer不維護關系
                  false(默認值): customer維護關系
    
              inverse屬性: 性能優(yōu)化.提高關系維護的性能.
              原則: 無論怎么放棄,總有一方必須要維護關系.
              一對多關系中: 一的一方放棄.也只能一的一方放棄.多的一方不能放棄.
            -->
          <set name="linkMens" inverse="true" cascade="delete"  >
              <key column="lkm_cust_id" ></key>
              <one-to-many class="LinkMan" />
          </set>
      </class>
    

    LinkMan.hbm.xml中(‘多’的一方):

      <class name="LinkMan" table="cst_linkman" >
          <id name="lkm_id"  >
              <generator class="native"></generator>
          </id>
          <property name="lkm_gender"  ></property>
          <property name="lkm_name"  ></property>
          <property name="lkm_phone"  ></property>
          <property name="lkm_email"  ></property>
          <property name="lkm_qq"  ></property>
          <property name="lkm_mobile"  ></property>
          <property name="lkm_memo"  ></property>
          <property name="lkm_position"  ></property>
          
          <!-- 多對一 -->
          <!-- 
              name屬性:引用屬性名
              column屬性: 外鍵列名
              class屬性: 與我關聯(lián)的對象完整類名
           -->
            <!-- 
              級聯(lián)操作:   cascade
                  save-update: 級聯(lián)保存更新
                  delete:級聯(lián)刪除
                  all:save-update+delete
              級聯(lián)操作: 簡化操作.目的就是為了少些兩行代碼.
            -->
            <!-- 多的一方: 不能放棄維護關系的.外鍵字段就在多的一方.  -->
          <many-to-one name="customer" column="lkm_cust_id" class="Customer"  >
          </many-to-one>
      </class>
    
  • 操作關聯(lián)屬性:

    • 基本操作
      //一對多|多對一關系操作
      public class Demo {
      @Test
      //保存客戶 以及客戶 下的聯(lián)系人
      public void fun1(){
          //1 獲得session
          Session session = HibernateUtils.openSession();
          //2 開啟事務
          Transaction tx = session.beginTransaction();
          //-------------------------------------------------
          //3操作
          Customer c = new Customer();
          c.setCust_name("傳智播客");
          
          LinkMan lm1 = new LinkMan();
          lm1.setLkm_name("黎活明");
          
          LinkMan lm2 = new LinkMan();
          lm2.setLkm_name("劉悅東");
          
          //表達一對多,客戶下有多個聯(lián)系人
          c.getLinkMens().add(lm1);
          c.getLinkMens().add(lm2);
          
          //表達對對對,聯(lián)系人屬于哪個客戶
          lm1.setCustomer(c);
          lm2.setCustomer(c);
          
          
          session.save(c);
      /       session.save(lm1);
      /       session.save(lm2);
          
          //-------------------------------------------------
          //4提交事務
          tx.commit();
          //5關閉資源
          session.close();
      }
    
      @Test
      //為客戶增加聯(lián)系人
      public void fun2(){
          //1 獲得session
          Session session = HibernateUtils.openSession();
          //2 開啟事務
          Transaction tx = session.beginTransaction();
          //-------------------------------------------------
          //3操作
          //1> 獲得要操作的客戶對象
          Customer c = session.get(Customer.class,1l);
          //2> 創(chuàng)建聯(lián)系人
          LinkMan lm1 = new LinkMan();
          lm1.setLkm_name("郝強勇");
          //3> 將聯(lián)系人添加到客戶,將客戶設置到聯(lián)系人中
          c.getLinkMens().add(lm1);
          lm1.setCustomer(c);
          //4> 執(zhí)行保存
          session.save(lm1);
          //-------------------------------------------------
          //4提交事務
          tx.commit();
          //5關閉資源
          session.close();
      }
    
      @Test
      //為客戶刪除聯(lián)系人
      public void fun3(){
          //1 獲得session
          Session session = HibernateUtils.openSession();
          //2 開啟事務
          Transaction tx = session.beginTransaction();
          //-------------------------------------------------
          //3操作
          //1> 獲得要操作的客戶對象
          Customer c = session.get(Customer.class,1l);
          //2> 獲得要移除的聯(lián)系人
          LinkMan lm = session.get(LinkMan.class, 3l);
          //3> 將聯(lián)系人從客戶集合中移除
          c.getLinkMens().remove(lm);
          lm.setCustomer(null);
          //-------------------------------------------------
          //4提交事務
          tx.commit();
          //5關閉資源
          session.close();
      }
    }
    
    • 進階 - 級聯(lián)

      cascade屬性值:save-update,不建議delete

      級聯(lián)的效果只是簡化操作,可以少寫幾句代碼。

    
    //測試級聯(lián)操作
    public class Demo2 {
      @Test
      //保存客戶 以及客戶 下的聯(lián)系人
      //cascade:save-update
      public void fun1(){
          //1 獲得session
          Session session = HibernateUtils.openSession();
          //2 開啟事務
          Transaction tx = session.beginTransaction();
          //-------------------------------------------------
          //3操作
          Customer c = new Customer();
          c.setCust_name("傳智播客");
          
          LinkMan lm1 = new LinkMan();
          lm1.setLkm_name("黎活明");
          
          LinkMan lm2 = new LinkMan();
          lm2.setLkm_name("劉悅東");
          
          //表達一對多,客戶下有多個聯(lián)系人
          c.getLinkMens().add(lm1);
          c.getLinkMens().add(lm2);
          
          //表達對對對,聯(lián)系人屬于哪個客戶
          lm1.setCustomer(c);
          lm2.setCustomer(c);
          
          
          session.save(c);
    //        session.save(lm1);
    //        session.save(lm2);
          
          //-------------------------------------------------
          //4提交事務
          tx.commit();
          //5關閉資源
          session.close();
      }
      
      @Test
      //測試刪除客戶時,級聯(lián)刪除客戶下的聯(lián)系人
      //cascade:delete
      public void fun2(){
          //1 獲得session
          Session session = HibernateUtils.openSession();
          //2 開啟事務
          Transaction tx = session.beginTransaction();
          //-------------------------------------------------
          //3操作
          //1> 獲得要操作的客戶對象
          Customer c = session.get(Customer.class,1l);
          //2>調用delete刪除客戶
          session.delete(c);
          //-------------------------------------------------
          //4提交事務
          tx.commit();
          //5關閉資源
          session.close();
      }
      
      @Test
      //保存聯(lián)系人以及聯(lián)系人對應的客戶
      //cascade:save-update
      public void fun3(){
          //1 獲得session
          Session session = HibernateUtils.openSession();
          //2 開啟事務
          Transaction tx = session.beginTransaction();
          //-------------------------------------------------
          //3操作
          Customer c = new Customer();
          c.setCust_name("北大青鳥");
          
          LinkMan lm1 = new LinkMan();
          lm1.setLkm_name("劉總");
          
          //表達一對多,客戶下有多個聯(lián)系人
          c.getLinkMens().add(lm1);
          
          //表達對對對,聯(lián)系人屬于哪個客戶
          lm1.setCustomer(c);
          
          
          session.save(lm1);
          
          //-------------------------------------------------
          //4提交事務
          tx.commit();
          //5關閉資源
          session.close();
      }
          
    }
    
    • 進階 - 關系維護

      優(yōu)化性能效率:在保存時.兩方都會維護外鍵關系.關系維護兩次,冗余了. 多余的維護關系語句,顯然是客戶這一端在維護關系。

      inverse屬性值true時表示當前配置的這一方放棄維護(字面意思反轉嘛),默認為false。

    //操作進階--關系維護屬性
    public class Demo3 {
      @Test
      //保存客戶 以及客戶 下的聯(lián)系人
      public void fun1(){
          //1 獲得session
          Session session = HibernateUtils.openSession();
          //2 開啟事務
          Transaction tx = session.beginTransaction();
          //-------------------------------------------------
          //3操作
          Customer c = new Customer();
          c.setCust_name("傳智播客");
          
          LinkMan lm1 = new LinkMan();
          lm1.setLkm_name("黎活明");
          
          LinkMan lm2 = new LinkMan();
          lm2.setLkm_name("劉悅東");
          
          //表達一對多,客戶下有多個聯(lián)系人. 
          // 如果客戶放棄維護與聯(lián)系人的關系. 維護關系的代碼可以省略
          //c.getLinkMens().add(lm1);
          //c.getLinkMens().add(lm2);
          
          //表達對對對,聯(lián)系人屬于哪個客戶
          lm1.setCustomer(c);
          lm2.setCustomer(c);
          
          
          session.save(c);
          session.save(lm1);
          session.save(lm2);
          
          //-------------------------------------------------
          //4提交事務
          tx.commit();
          //5關閉資源
          session.close();
      }
      
      @Test
      //刪除客戶
      public void fun2(){
          //1 獲得session
          Session session = HibernateUtils.openSession();
          //2 開啟事務
          Transaction tx = session.beginTransaction();
          //-------------------------------------------------
          //3操作
          Customer customer = session.get(Customer.class, 1l);
          
          session.delete(customer);
          //-------------------------------------------------
          //4提交事務
          tx.commit();
          //5關閉資源
          session.close();
      }
          
    }
    

多對多

數(shù)據(jù)表中

員工表

uid uname
1 張三
2 李四
3 王五

角色表

rid rname
1 清潔工
2 總裁
3 前臺

員工角色表(采用中間表設計原則)

uid rid
1 1
1 3
2 2
3 1

實體中:(使用集合來表達互相擁有多個對方)

員工(User)

private Long uid;
private String uname;
private Set<Role> roles;

角色(Role)

private Long rid;
private String rname;
private Set<User> users;

orm元數(shù)據(jù)中

User.hbm.xml

    <class name="User" table="sys_user" >
        <id name="user_id"  >
            <generator class="native"></generator>
        </id>
        <property name="user_code"  ></property>
        <property name="user_name"  ></property>
        <property name="user_password"  ></property>
        <property name="user_state"  ></property>
    
        <!-- 多對多關系表達 -->
        <!-- 
            name: 集合屬性名
            table: 配置中間表名
            key
             |-column:外鍵,別人引用"我"的外鍵列名
             class: 我與哪個類是多對多關系
             column:外鍵.我引用比人的外鍵列名
         -->
         <!-- cascade級聯(lián)操作:
                    save-update: 級聯(lián)保存更新
                    delete:級聯(lián)刪除
                    all:級聯(lián)保存更新+級聯(lián)刪除
            結論: cascade簡化代碼書寫.該屬性使不使用無所謂. 建議要用只用save-update.
                 如果使用delete操作太過危險.尤其在多對多中.不建議使用.
                     -->
        <set name="roles" table="sys_user_role" cascade="save-update" >
            <key column="user_id" ></key>
            <many-to-many class="Role" column="role_id" ></many-to-many>
        </set>
    
    </class>

Role.hbm.xml

    <class name="Role" table="sys_role" >
        <id name="role_id"  >
            <generator class="native"></generator>
        </id>
        <property name="role_name"  ></property>
        <property name="role_memo"  ></property>

    <!-- 使用inverse屬性
            true: 放棄維護外鍵關系
            false(默認值):維護關系
            
        結論: 將來在開發(fā)中,如果遇到多對多關系.一定要選擇一方放棄維護關系.
             一般誰來放棄要看業(yè)務方向. 例如錄入員工時,需要為員工指定所屬角色.
             那么業(yè)務方向就是由員工維護角色. 角色不需要維護與員工關系.角色放棄維護
         -->        
        <set name="users" table="sys_user_role" inverse="true" >
            <key column="role_id" ></key>
            <many-to-many class="User" column="user_id" ></many-to-many>
        </set>
    </class>
  • 操作關聯(lián)屬性

    基本操作

    //多對多關系操作
    public class Demo {
      @Test
      //保存員工以及角色
      public void fun1(){
          //1 獲得session
          Session session = HibernateUtils.openSession();
          //2 開啟事務
          Transaction tx = session.beginTransaction();
          //-------------------------------------------------
          //3操作
          //1> 創(chuàng)建兩個 User
          User u1 = new User();
          u1.setUser_name("郝強勇");
          
          User u2 = new User();
          u2.setUser_name("金家德");
          
          //2> 創(chuàng)建兩個 Role
          Role r1 = new Role();
          r1.setRole_name("保潔");
          
          Role r2 = new Role();
          r2.setRole_name("保安");
          //3> 用戶表達關系
          u1.getRoles().add(r1);
          u1.getRoles().add(r2);
          
          u2.getRoles().add(r1);
          u2.getRoles().add(r2);
          
          //4> 角色表達關系
          r1.getUsers().add(u1);
          r1.getUsers().add(u2);
          
          r2.getUsers().add(u1);
          r2.getUsers().add(u2);
          
          //5> 調用Save方法一次保存
          session.save(u1);
          session.save(u2);
          session.save(r1);
          session.save(r2);
          //-------------------------------------------------
          //4提交事務
          tx.commit();
          //5關閉資源
          session.close();
      }
      
      
      @Test
      //為郝強勇新增一個角色
      public void fun3(){
          //1 獲得session
          Session session = HibernateUtils.openSession();
          //2 開啟事務
          Transaction tx = session.beginTransaction();
          //-------------------------------------------------
          //3操作
          //1> 獲得郝強勇用戶
          User user = session.get(User.class, 1l);
          //2> 創(chuàng)建公關角色
          Role r = new Role();
          r.setRole_name("男公關");
          //3> 將角色添加到用戶中
          user.getRoles().add(r);
          //4> 將角色轉換為持久化
          //session.save(r);
          //若在User.hbm.xml中配置了cascade屬性為save-update,則可以級聯(lián)保存,就不必寫上面這句代碼
          //-------------------------------------------------
          //4提交事務
          tx.commit();
          //5關閉資源
          session.close();
      }
      
      @Test
      //為郝強勇解除一個角色
      public void fun4(){
          //1 獲得session
          Session session = HibernateUtils.openSession();
          //2 開啟事務
          Transaction tx = session.beginTransaction();
          //-------------------------------------------------
          //3操作
          //1> 獲得郝強勇用戶
          User user = session.get(User.class, 1l);
          //2> 獲得要操作的角色對象(保潔,保安)
          Role r1 = session.get(Role.class, 1l);
          Role r2 = session.get(Role.class, 2l);
          //3> 將角色從用戶的角色集合中移除
          user.getRoles().remove(r1);
          user.getRoles().remove(r2);
          
          //-------------------------------------------------
          //4提交事務
          tx.commit();
          //5關閉資源
          session.close();
      }
    }
    

    進階 - inverse屬性:

    使用inverse屬性
              true: 放棄維護外鍵關系
              false(默認值):維護關系
              
          結論: 將來在開發(fā)中,如果遇到多對多關系.一定要選擇一方放棄維護關系.
               一般誰來放棄要看業(yè)務方向. 例如錄入員工時,需要為員工指定所屬角色.
               那么業(yè)務方向就是由員工維護角色. 角色不需要維護與員工關系.角色放棄維護
    

    進階 - 級聯(lián)屬性

    cascade級聯(lián)操作:
                      save-update: 級聯(lián)保存更新
                      delete:級聯(lián)刪除
                      all:級聯(lián)保存更新+級聯(lián)刪除
              結論: cascade簡化代碼書寫.該屬性使不使用無所謂. 建議要用只用save-update.
                   如果使用delete操作太過危險.尤其在多對多中.不建議使用.
    

    ?

    ?

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • hibernate(20170731) 1.導包:hibernate-distribution-3.5.6-Fin...
    瀟湘雨smile閱讀 755評論 0 0
  • 本文約定: 1. Nhibernate簡寫為NHB; 2. 本文例子的開發(fā)平臺為win2000pro+sp4, s...
    壹米玖坤閱讀 604評論 0 0
  • 本文包括: 1、CRM 項目的整體介紹 2、Hibernate 框架概述 3、Hibernate 快速入門 4、H...
    廖少少閱讀 3,533評論 9 66
  • 時間忘了我 有時把我丟在暮色里 有時又是寂寥深夜 甚至是天色漸開的黎明 我也忘了時間
    拾月和初一閱讀 307評論 0 5
  • threading與Lock# Python中實現(xiàn)多線程的方式有Thread和threading,其中Thread...
    FangHao閱讀 163評論 0 0

友情鏈接更多精彩內容