一對多、多對一
在表中表達:外鍵
在對象中的表達:集合(使用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>