一對多、多對一、多對多關系


一對多、多對一

在表中表達:外鍵

在對象中的表達:集合(使用Set集合)

在orm元數據文件中配置:

在上述實體中添加了相應的集合(Set<LinkMan>)跟對象(Customer)屬性后,就得在orm元數據中去配置這兩個屬性了

在一的一方配置(即擁有集合的一方)

在Customer.hbm.xml中寫入

<!--
    name: 填寫集合屬性名
    column: 外鍵名(數據庫表中的外鍵名)
    class: 與我關聯的類的名稱,即多的一方的實體類名
-->
<set name="linkman">
    <!-- 要指定的外鍵列名 -->
    <key column="lkm_cust_id"></key>
    <!-- 指定對應的關系:一對多 -->
    <one-to-many class="LinkMan" />
</set>

在多的一方配置

在LinkMan.hbm.xml中寫入

<!--
    name: 屬性名
    column: 外鍵列名
    class: 與我關聯的類的名稱,即一的一方的實體類的名稱
-->
<many-to-one name="customer" column="lkm_cust_id" class="Customer">
</many_to_one>

一對多關系操作

創建客戶跟聯系人,並指定客戶對應的聯系人

public void test(){
    // 獲取session
    Session session = HBUtils.CurrentSession();
    // 獲取事務並開啟
    Transaction tx = session.beginTransaction();
    // -------------------------------------
        // 創建客戶跟聯系人
    Customer customer = new Customer();
    customer.setCust_name("Sacrtlett");
        // 創建客戶
    LinkMan linkMan = new LinkMan();
    linkMan.setLkm_name("Eric Jin");
		
    LinkMan linkMan1 = new LinkMan();
    linkMan1.setLkm_name("taylor");
		
        // 添加關系
    customer.getLinkMens().add(linkMan);
    customer.getLinkMens().add(linkMan1);
		
    linkMan.setCustomer(customer);
    linkMan1.setCustomer(customer); 
        // 保存
    session.save(customer);
    session.save(linkMan);
    session.save(linkMan1);
    // -------------------------------------
    // 提交事務
    tx.commit();
}

為客戶添加聯系人

public void test(){
    // 獲取session
    Session session = HBUtils.CurrentSession();
    // 獲取事務並開啟
    Transaction tx = session.beginTransaction();
    // -------------------------------------
        // 獲取要操作的客戶
    Customer c = session.get(Customer.class, 1L);
        // 創建聯系人
    LinkMan linkMan = new LinkMan();
    linkMan.setLkm_name("mike");
		
        // 將聯系人添加到客戶,將客戶設置到聯系人中
    c.getLinkMens().add(linkMan);
		
    linkMan.setCustomer(c);
        // 保存
    session.save(linkMan);
    // -------------------------------------
    // 提交事務
    tx.commit();
}

解除客戶與聯系人的關系

public void test(){
    // 獲取session
    Session session = HBUtils.CurrentSession();
    // 獲取事務並開啟
    Transaction tx = session.beginTransaction();
    // -------------------------------------
        // 獲取要操作的客戶
    Customer c = session.get(Customer.class, 1L);
        // 獲取要移除的聯系人
    LinkMan lm = session.get(LinkMan.class, 1L);
        // 將聯系人從客戶集合集合中刪除
    c.getLinkMens().remove(lm);
		
    lm.setCustomer(null);
    // -------------------------------------
    // 提交事務
    tx.commit();
}

多對多

在表中表達

上面的圖片中,通過第三方的一張表將Author表跟Book表聯系了起來,而這第三方表最少應該有兩列,一列是與Author表的id關聯的外鍵,一列是與Book表關聯的外鍵。

在上圖中,第三張表的Author_id的跟Book_id中1對應了1,1還對應了2,這表示大灰狼參與編寫了java編程跟python精通這兩本書。而3也與1對應了,這表示參與了編寫java精通的還有大老虎,

一個作者可以編寫多本書,而一本書也可以由多個作者編寫,這很好的體現了多對多的思想

在對象中表達

在orm元數據文件中配置:

由於都是多的一方,所以兩方的配置應該是一模一樣的,只是需要把相應的參數修改一下就可以了

在Author.hbm.xml中寫入

<!--  
    name: 實體勒種集合的屬性名
    tables: 配置第三張表的表名
    key下面的column: 外鍵名,第三張表與我關聯的外鍵名
    class: 與我關聯的類名,即另外一方的實體類的類名
    many-to-many: 我引用別人的外鍵,即第三張表與另外一方關聯的外鍵名
-->
<set name="book" tables="sys_author_book">
    <!-- 要指定的外鍵名 -->
    <key column="author_id"></key>
    <!-- 指定對應關系 -->
    <many-to-many class="Book" column="book_id" />
</set>

在Book.hbm.xml中寫入

由於都是多的一方,所以只需要把相應的參數做一下修改即可

<set name="author" tables="sys_author_book">
    <!-- 要指定的外鍵名 -->
    <key column="book_id"></key>
    <!-- 指定對應關系 -->
    <many-to-many class="Author" column="author_id" />
</set>

多對多關系操作

添加關聯

public void test(){
    // 獲取session
    Session session = HBUtils.CurrentSession();
    // 獲取事務並開啟
    Transaction tx = session.beginTransaction();
    // -------------------------------------
        // 創建兩個Author
    Author a1 = new Author();
    a1.setAuthor_name("大灰狼");
    Author a2 = new Author();
    a2.setAuthor_name("大熊貓");


        // 創建兩個Book
    Book b1 = new Book();
    b1.setBook_name("java編程");
    Book b2 = new Book();
    b2.setBook_name("python精通");

        // 作者關系表達
    a1.getBook().add(b1);
    a1.getBook().add(b2);

    a2.getBook().add(b1);
        // 書籍關系表達
    /*
        在這里應該注意,在上面a1跟a2已經對第三方表進行了維護,已經往第三張表里面
        插入數據了,如果b1跟b2再去維護,在往是第三張表里面插入數據就會出錯,所以
        不需要再讓書籍去維護,硬是要維護也行,只需要去書籍的orm配置文件中將inverse
        配置成true放棄維護就可以了
    */
 
        // 保存
    session.save(a1);
    session.save(a2);
    session.save(b1);
    session.save(b2);
    // -------------------------------------
    // 提交事務
    tx.commit();
}

結論:將來在開發中,如果遇到多對多關系,一定要選擇一方放棄維護選擇放棄誰要根據業務需求來定,比如要給作者指定書籍,那么就給作者維護。如果要為書籍配備作者,就是指定書籍維護

為作者添加書籍  

public void test(){
    // 獲取session
    Session session = HBUtils.CurrentSession();
    // 獲取事務並開啟
    Transaction tx = session.beginTransaction();
    // -------------------------------------
        // 獲取Author
    Author a = session.get(Author.class, 1L);
        // 創建書籍
    Book b = new Book();
    b.setBook_name("c語言入門");
        // 將書籍與作者關聯
    a.getBook().add(b);

        // 保存
    session.save(b);
    // -------------------------------------
    // 提交事務
    tx.commit();
}

解除某個作者的一本書籍

public void test(){
    // 獲取session
    Session session = HBUtils.CurrentSession();
    // 獲取事務並開啟
    Transaction tx = session.beginTransaction();
    // -------------------------------------
        // 獲取Author
    Author a = session.get(Author.class, 1L);
        // 獲取書籍
    Book b = session.get(Book.class, 1L); 
        // 將書籍從角色中移除
    a.getBook().remove(b);
    // -------------------------------------
    // 提交事務
    tx.commit();
}

配置級聯跟是否維護

級聯操作:cascade

有的時候覺得像 ssession.save(b) session.save(a) 既要將Author的對象持久化又要將Book對象持久化太麻煩了,於是想在持久化作者的時候順便把書籍也持久化,這時就可以使用cascade級聯操作

級聯參數

        save-update: 級聯保存更新

        delete: 級聯刪除

        all: 相當於 save-update + delete

一對多中使用級聯

在主表設置:

<set name="linkMens" cascade="save-update">
    <!-- 要指定的外鍵列名 -->
    <key column="lkm_cust_id"></key>
    <!-- 指定對應關系 -->
    <one-to-many clss="linkMan" />
</set>	

也可以在從表設置:

<many-to-one name="customer" column="lkm_cust_id" class="Customer" cascade="all"></many-to-one>

在設置之后就可以在session.save(a)的時候也session.save(b)了

注意: 一般不建議設置cascade的屬性為delete,太危險!

多對多中使用級聯

<set name="author" tables="sys_author_book" cascade="all">
    <!-- 要指定的外鍵名 -->
    <key column="book_id"></key>
    <!-- 指定對應關系 -->
    <many-to-many class="Author" column="author_id" />
</set>

注意:在多對多中一般不建議使用級聯

配置關系是否維護

在操作一對多或者多對多的時候,兩方都會對外鍵進行維護,這顯得很多余,降低效率,甚至在多對多中都去維護還會報錯!只需要由一方維護就可以了,這時可以通過設置inverse來讓一方放棄維護而全權交由對方去維護

inverse屬性:   

        true:當前配置的對象不維護關系,全權交由另一方維護

        false(默認):當前配置的對象自己維護關系

一對多

<!-- 設置用戶對象不維護,交由聯系人對象維護 -->
<set name="linkMens" inverse="true">
    <!-- 要指定的外鍵列名 -->
    <key column="lkm_cust_id"></key>
    <!-- 指定對應關系 -->
    <one-to-many clss="linkMan" />
</set>	

當設置了不再維護后,那么客戶維護聯系人的代碼可以省略
// c.getLinkMans().add(lm1);
// c.getLinkMans().add(lm2);

注意:只能是一的一方放棄維護,多的一方含有外鍵,不能自己放棄自己
如果放棄了維護,那么在一的一方在刪除數據時,由於沒有維護,會不允許刪除,因為已經被聯系人關聯了,這時必須使一的一方也維護

多對多

多對多不管哪一方都能放棄維護,至於具體是哪一方放棄維護,要根據項目的實際情況來定

<!-- Book放棄維護,交給Author去維護 -->
<set name="author" tables="sys_author_book" inverse="true">
    <!-- 要指定的外鍵名 -->
    <key column="book_id"></key>
    <!-- 指定對應關系 -->
    <many-to-many class="Author" column="author_id" />
</set>

  

 


免責聲明!

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



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