JavaWeb - Hibernate框架使用(三)

表與表的關(guān)系

關(guān)鍵是維護(hù)關(guān)聯(lián)屬性

一對多|多對一

一對多(多對一):

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

客戶表

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

? 聯(lián)系人表

lid lname cid
1 張總 1
2 劉總 1
3 王總 2
  • 實(shí)體中:

    客戶(Cudtomer)實(shí)體:

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

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

    private Long lid;
    private String lname;
    //使用對象引用‘一’的一方表達(dá)‘多’的一方屬于哪個‘一’的一方
    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>
      
          <!-- 集合,一對多關(guān)系,在配置文件中配置 -->
          <!-- 
              name屬性:集合屬性名
              column屬性: 外鍵列名
              class屬性: 與我關(guān)聯(lián)的對象完整類名
           -->
           <!-- 
              級聯(lián)操作:   cascade
                  save-update: 級聯(lián)保存更新
                  delete:級聯(lián)刪除
                  all:save-update+delete
              級聯(lián)操作: 簡化操作.目的就是為了少些兩行代碼.
            -->
            <!-- inverse屬性: 配置關(guān)系是否維護(hù). 
                  true: customer不維護(hù)關(guān)系
                  false(默認(rèn)值): customer維護(hù)關(guān)系
    
              inverse屬性: 性能優(yōu)化.提高關(guān)系維護(hù)的性能.
              原則: 無論怎么放棄,總有一方必須要維護(hù)關(guān)系.
              一對多關(guān)系中: 一的一方放棄.也只能一的一方放棄.多的一方不能放棄.
            -->
          <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屬性: 與我關(guān)聯(lián)的對象完整類名
           -->
            <!-- 
              級聯(lián)操作:   cascade
                  save-update: 級聯(lián)保存更新
                  delete:級聯(lián)刪除
                  all:save-update+delete
              級聯(lián)操作: 簡化操作.目的就是為了少些兩行代碼.
            -->
            <!-- 多的一方: 不能放棄維護(hù)關(guān)系的.外鍵字段就在多的一方.  -->
          <many-to-one name="customer" column="lkm_cust_id" class="Customer"  >
          </many-to-one>
      </class>
    
  • 操作關(guān)聯(lián)屬性:

    • 基本操作
      //一對多|多對一關(guān)系操作
      public class Demo {
      @Test
      //保存客戶 以及客戶 下的聯(lián)系人
      public void fun1(){
          //1 獲得session
          Session session = HibernateUtils.openSession();
          //2 開啟事務(wù)
          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("劉悅東");
          
          //表達(dá)一對多,客戶下有多個聯(lián)系人
          c.getLinkMens().add(lm1);
          c.getLinkMens().add(lm2);
          
          //表達(dá)對對對,聯(lián)系人屬于哪個客戶
          lm1.setCustomer(c);
          lm2.setCustomer(c);
          
          
          session.save(c);
      /       session.save(lm1);
      /       session.save(lm2);
          
          //-------------------------------------------------
          //4提交事務(wù)
          tx.commit();
          //5關(guān)閉資源
          session.close();
      }
    
      @Test
      //為客戶增加聯(lián)系人
      public void fun2(){
          //1 獲得session
          Session session = HibernateUtils.openSession();
          //2 開啟事務(wù)
          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("郝強(qiáng)勇");
          //3> 將聯(lián)系人添加到客戶,將客戶設(shè)置到聯(lián)系人中
          c.getLinkMens().add(lm1);
          lm1.setCustomer(c);
          //4> 執(zhí)行保存
          session.save(lm1);
          //-------------------------------------------------
          //4提交事務(wù)
          tx.commit();
          //5關(guān)閉資源
          session.close();
      }
    
      @Test
      //為客戶刪除聯(lián)系人
      public void fun3(){
          //1 獲得session
          Session session = HibernateUtils.openSession();
          //2 開啟事務(wù)
          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提交事務(wù)
          tx.commit();
          //5關(guān)閉資源
          session.close();
      }
    }
    
    • 進(jìn)階 - 級聯(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 開啟事務(wù)
          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("劉悅東");
          
          //表達(dá)一對多,客戶下有多個聯(lián)系人
          c.getLinkMens().add(lm1);
          c.getLinkMens().add(lm2);
          
          //表達(dá)對對對,聯(lián)系人屬于哪個客戶
          lm1.setCustomer(c);
          lm2.setCustomer(c);
          
          
          session.save(c);
    //        session.save(lm1);
    //        session.save(lm2);
          
          //-------------------------------------------------
          //4提交事務(wù)
          tx.commit();
          //5關(guān)閉資源
          session.close();
      }
      
      @Test
      //測試刪除客戶時,級聯(lián)刪除客戶下的聯(lián)系人
      //cascade:delete
      public void fun2(){
          //1 獲得session
          Session session = HibernateUtils.openSession();
          //2 開啟事務(wù)
          Transaction tx = session.beginTransaction();
          //-------------------------------------------------
          //3操作
          //1> 獲得要操作的客戶對象
          Customer c = session.get(Customer.class,1l);
          //2>調(diào)用delete刪除客戶
          session.delete(c);
          //-------------------------------------------------
          //4提交事務(wù)
          tx.commit();
          //5關(guān)閉資源
          session.close();
      }
      
      @Test
      //保存聯(lián)系人以及聯(lián)系人對應(yīng)的客戶
      //cascade:save-update
      public void fun3(){
          //1 獲得session
          Session session = HibernateUtils.openSession();
          //2 開啟事務(wù)
          Transaction tx = session.beginTransaction();
          //-------------------------------------------------
          //3操作
          Customer c = new Customer();
          c.setCust_name("北大青鳥");
          
          LinkMan lm1 = new LinkMan();
          lm1.setLkm_name("劉總");
          
          //表達(dá)一對多,客戶下有多個聯(lián)系人
          c.getLinkMens().add(lm1);
          
          //表達(dá)對對對,聯(lián)系人屬于哪個客戶
          lm1.setCustomer(c);
          
          
          session.save(lm1);
          
          //-------------------------------------------------
          //4提交事務(wù)
          tx.commit();
          //5關(guān)閉資源
          session.close();
      }
          
    }
    
    • 進(jìn)階 - 關(guān)系維護(hù)

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

      inverse屬性值true時表示當(dāng)前配置的這一方放棄維護(hù)(字面意思反轉(zhuǎn)嘛)裙顽,默認(rèn)為false。

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

多對多

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

員工表

uid uname
1 張三
2 李四
3 王五

角色表

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

員工角色表(采用中間表設(shè)計(jì)原則)

uid rid
1 1
1 3
2 2
3 1

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

員工(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>
    
        <!-- 多對多關(guān)系表達(dá) -->
        <!-- 
            name: 集合屬性名
            table: 配置中間表名
            key
             |-column:外鍵,別人引用"我"的外鍵列名
             class: 我與哪個類是多對多關(guān)系
             column:外鍵.我引用比人的外鍵列名
         -->
         <!-- cascade級聯(lián)操作:
                    save-update: 級聯(lián)保存更新
                    delete:級聯(lián)刪除
                    all:級聯(lián)保存更新+級聯(lián)刪除
            結(jié)論: 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: 放棄維護(hù)外鍵關(guān)系
            false(默認(rèn)值):維護(hù)關(guān)系
            
        結(jié)論: 將來在開發(fā)中,如果遇到多對多關(guān)系.一定要選擇一方放棄維護(hù)關(guān)系.
             一般誰來放棄要看業(yè)務(wù)方向. 例如錄入員工時,需要為員工指定所屬角色.
             那么業(yè)務(wù)方向就是由員工維護(hù)角色. 角色不需要維護(hù)與員工關(guān)系.角色放棄維護(hù)
         -->        
        <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>
  • 操作關(guān)聯(lián)屬性

    基本操作

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

    進(jìn)階 - inverse屬性:

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

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

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

    ?

    ?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市闻丑,隨后出現(xiàn)的幾起案子漩怎,更是在濱河造成了極大的恐慌,老刑警劉巖嗦嗡,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件勋锤,死亡現(xiàn)場離奇詭異,居然都是意外死亡侥祭,警方通過查閱死者的電腦和手機(jī)叁执,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來矮冬,“玉大人谈宛,你說我怎么就攤上這事√ナ穑” “怎么了入挣?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵,是天一觀的道長硝拧。 經(jīng)常有香客問我径筏,道長,這世上最難降的妖魔是什么障陶? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任滋恬,我火速辦了婚禮,結(jié)果婚禮上抱究,老公的妹妹穿的比我還像新娘恢氯。我一直安慰自己,他們只是感情好鼓寺,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布勋拟。 她就那樣靜靜地躺著,像睡著了一般妈候。 火紅的嫁衣襯著肌膚如雪敢靡。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天苦银,我揣著相機(jī)與錄音啸胧,去河邊找鬼。 笑死幔虏,一個胖子當(dāng)著我的面吹牛纺念,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播想括,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼陷谱,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了瑟蜈?” 一聲冷哼從身側(cè)響起烟逊,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎踪栋,沒想到半個月后焙格,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡夷都,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年眷唉,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片囤官。...
    茶點(diǎn)故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡冬阳,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出党饮,到底是詐尸還是另有隱情肝陪,我是刑警寧澤,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布刑顺,位于F島的核電站氯窍,受9級特大地震影響饲常,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜狼讨,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一贝淤、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧政供,春花似錦播聪、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至衅檀,卻和暖如春招刨,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背术吝。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工计济, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人排苍。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓沦寂,卻偏偏與公主長得像,于是被迫代替她去往敵國和親淘衙。 傳聞我的和親對象是個殘疾皇子传藏,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評論 2 348

推薦閱讀更多精彩內(nèi)容

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