Hibernate學習(七)
表與表之間關係回顧
1 一對多
(1)分類和商品的關係,一個分類裡面有多個商品,一個商品只能屬於一個分類。
(2)客戶和聯絡人是一對多關係
客戶:與公司有業務往來,百度、新浪、360
聯絡人:公司裡面的員工,百度裡面有很多的員工,聯絡員工
**公司和公司員工的關係
客戶是一,聯絡人是多,
一個客戶裡面有多個聯絡人,一個聯絡人只能屬於一個客戶
(3)一對多建表:通過外來鍵建立關係
2 多對多
(1)訂單和商品關係,一個訂單裡面有偶多個商品,一個商品屬於多個訂單
(2)使用者和角色多對多關係
使用者:小王,小馬,小宋
角色:總經理,祕書,司機,保安
**比如小王可以是總經理、四級
**比如小宋可以是四級、祕書、保安
比如小馬,可以是祕書、總經理
---一個使用者裡面可以有多個角色,一個角色可以有多個使用者
(3)多對多建表,建立第三張表維護關係
3 一對一
(1)在中國,一個男人只能有一個妻子,一個女人只能有一個丈夫
Hibernate的一對多操作(重點)
一對多對映配置
以客戶和聯絡人為例:客戶是一,聯絡人是多第一步,建立兩個實體類,客戶和聯絡人
package cn.itcase.hibernate; import java.util.HashSet; import java.util.Set; public class Customer { private Integer cid; private String custLevel; private String custMoblie; private String custName; private String custPhone; private String custSource; //在客戶實體類裡面表示多個聯絡人,一個客戶有多個聯絡人 //hibernate要求使用集合表示多的資料,使用set集合 private Set<LinkMan> setLinkMan=new HashSet<LinkMan>(); public Set<LinkMan> getSetLinkMan() { return setLinkMan; } public void setSetLinkMan(Set<LinkMan> setLinkMan) { this.setLinkMan = setLinkMan; } public Integer getCid() { return cid; } public void setCid(Integer cid) { this.cid = cid; } public String getCustLevel() { return custLevel; } public void setCustLevel(String custLevel) { this.custLevel = custLevel; } public String getCustMoblie() { return custMoblie; } public void setCustMoblie(String custMoblie) { this.custMoblie = custMoblie; } public String getCustName() { return custName; } public void setCustName(String custName) { this.custName = custName; } public String getCustPhone() { return custPhone; } public void setCustPhone(String custPhone) { this.custPhone = custPhone; } public String getCustSource() { return custSource; } public void setCustSource(String custSource) { this.custSource = custSource; } }
package cn.itcase.hibernate; public class LinkMan { private Integer lkm_id; private String lkm_gender; private String lkm_name; private String lkm_phone; //在聯絡人實體類裡面表示所屬客戶,一個聯絡人只能屬於一個客戶 private Customer customer; public Customer getCustomer() { return customer; } public void setCustomer(Customer customer) { this.customer = customer; } public Integer getLkm_id() { return lkm_id; } public void setLkm_id(Integer lkm_id) { this.lkm_id = lkm_id; } public String getLkm_gender() { return lkm_gender; } public void setLkm_gender(String lkm_gender) { this.lkm_gender = lkm_gender; } public String getLkm_name() { return lkm_name; } public void setLkm_name(String lkm_name) { this.lkm_name = lkm_name; } public String getLkm_phone() { return lkm_phone; } public void setLkm_phone(String lkm_phone) { this.lkm_phone = lkm_phone; } }
第二步,讓兩個實體類之間相互表示
(1)在客戶實體類裡面表示多個聯絡人
一個客戶裡面有多個聯絡人
//在客戶實體類裡面表示多個聯絡人,一個客戶有多個聯絡人
//hibernate要求使用集合表示多的資料,使用set集合
private Set<LinkMan> setLinkMan=new HashSet<LinkMan>();
public Set<LinkMan> getSetLinkMan() {
return setLinkMan;
}
public void setSetLinkMan(Set<LinkMan> setLinkMan) {
this.setLinkMan = setLinkMan;
}
(2)在聯絡人實體類裡面表示所屬客戶
一個聯絡人只能屬於一個客戶
第三步,配置對映關係
(1)一般一個實體類對應一個對映檔案
(2)把對映最基本配置完成
(3)在配置檔案中,配置一對多的關係
在客戶對映檔案中,表示所有聯絡人
<!-- 在客戶對映檔案中,表示所有聯絡人
使用set標籤標識所有的聯絡人
set標籤裡面有name屬性,屬性值解除安裝客戶實體類裡面表示聯絡人的set集合名稱
-->
<set name="setLinkMan">
<!-- 一對多建表,有外來鍵,
hibernate機制,雙向維護外來鍵,在一和多那一方面都配置外來鍵 -->
<key column = "clid"></key>
<!-- 客戶所有的聯絡人,class裡面寫聯絡人實體類的全路徑 -->
<one-to-many class="cn.itcase.hibernate.LinkMan"/>
</set>
在聯絡人對映檔案中,表示所屬
<!-- 表示聯絡人所屬客戶
name屬性:因為在聯絡人實體類使用customer物件表示,寫customer名稱
column屬性:外來鍵名稱
-->
<many-to-one name="customer" class="cn.itcase.hibernate.Customer" column="clid"></many-to-one>
第四步 建立核心配置檔案,把對映檔案引入到核心配置檔案中
<!-- 第三部分:把對映檔案放到核心檔案中來 必須的 -->
<mapping resource="cn/itcase/hibernate/Customer.hbm.xml"/>
<mapping resource="cn/itcase/hibernate/LinkMan.hbm.xml"/>
測試如下:
一對多級聯操作
級聯操作
1 級聯儲存
(1)新增一個客戶,為這個客戶新增多個聯絡人
2 級聯刪除
(1)刪除一個客戶,這個客戶裡面所有的聯絡人也刪除
一對多級聯儲存
1 新增客戶 ,為這個客戶新增一個聯絡人
@Test
public void testAddDemo1() {
SessionFactory sessionFactory=HibernateUtils.getSessionFactory();
Session session=sessionFactory.openSession();
Transaction tx=session.beginTransaction();
//新增一個客戶,為這個客戶新增一個聯絡人
//1 建立客戶和聯絡人物件
Customer customer=new Customer();
customer.setCustName("創智播客");
customer.setCustLevel("Vip");
customer.setCustSource("網路");
customer.setCustPhone("110");
customer.setCustMoblie("999");
LinkMan linkman=new LinkMan();
linkman.setLkm_name("lucy");
linkman.setLkm_gender("男");
linkman.setLkm_phone("911");
//2 在客戶表示所有聯絡人,在聯絡人表示客戶
//建立客戶物件和聯絡人物件關係
//2.1把聯絡人放到客戶實體類物件的set集合裡面
customer.getSetLinkMan().add(linkman);
//2.2把客戶物件放到聯絡人裡面
linkman.setCustomer(customer);
//儲存到資料庫
session.save(customer);
session.save(linkman);
tx.commit();
session.close();
sessionFactory.close();
}
(2)簡化寫法
一般根據客戶新增聯絡人
第一步 在客戶對映檔案在進行配置
在客戶對映檔案裡面set標籤進行配置
<set name="setLinkMan" cascade="save-update">
第二步 建立客戶和聯絡人物件,只需把聯絡人放大客戶裡面就可以了 @Test
public void testAddDemo2() {
SessionFactory sessionFactory=HibernateUtils.getSessionFactory();
Session session=sessionFactory.openSession();
Transaction tx=session.beginTransaction();
//新增一個客戶,為這個客戶新增一個聯絡人
//1 建立客戶和聯絡人物件
Customer customer=new Customer();
customer.setCustName("百度");
customer.setCustLevel("普通客戶");
customer.setCustSource("網路");
customer.setCustPhone("110");
customer.setCustMoblie("999");
LinkMan linkman=new LinkMan();
linkman.setLkm_name("小紅");
linkman.setLkm_gender("女");
linkman.setLkm_phone("911");
//2把聯絡人放到客戶裡面
customer.getSetLinkMan().add(linkman);
//3儲存客戶
session.save(customer);
tx.commit();
session.close();
sessionFactory.close();
}
2一對多級聯刪除1 刪除某個客戶,把客戶裡面所有的聯絡人刪除
2 具體實現
第一步 在客戶對映檔案set標籤,進行配置
(1)使用屬性cascade屬性值delete
<set name="setLinkMan" cascade="save-update,delete">
第二步 在程式碼中直接刪除客戶
(1)根據id查詢物件,呼叫session裡面的delete方法刪除
@Test
public void testAddDemo3() {
SessionFactory sessionFactory=HibernateUtils.getSessionFactory();
Session session=sessionFactory.openSession();
Transaction tx=session.beginTransaction();
// 1 根據id查詢客戶物件
Customer customer=session.get(Customer.class, 2);
// 2 呼叫方法進行刪除
session.delete(customer);
tx.commit();
session.close();
sessionFactory.close();
}
執行過程
(1)根據id查詢客戶
(2)根據外來鍵id值查詢聯絡人
(3)把聯絡人外來鍵設定為null
(4)刪除聯絡人和客戶
一對多修改操作
1 讓lucy聯絡人所屬客戶不是傳智播客,而是騰訊
@Test
public void testUpdate() {
SessionFactory sessionFactory=HibernateUtils.getSessionFactory();
Session session=sessionFactory.openSession();
Transaction tx=session.beginTransaction();
//1根據id查詢lucy聯絡人,根據id查詢騰訊客戶
Customer tengxun=session.get(Customer.class, 3);
LinkMan lucy=session.get(LinkMan.class, 1);
//2設定持久太物件值
//把聯絡人放客戶裡面
tengxun.getSetLinkMan().add(lucy);
lucy.setCustomer(tengxun);
tx.commit();
session.close();
sessionFactory.close();
}
2 inverse屬性
(1)因為hibernate雙向維護外來鍵,在客戶和聯絡人裡面都需要維護外來鍵,修改客戶時候,修改一次外來鍵,修改聯絡人時候也修改一次外來鍵,造成效率問題。
(2)解決方式:讓其中一方不維護外來鍵
一對多裡面,讓其中一方放棄外來鍵維護,
一個國家有總統,國家有很多人,總統不能認識國家所有人,國家所有人可以認識總統。
(3)具體實現
在放棄關係維護對映檔案中,進行配置,在set標籤上使用inverse屬性。
inverse屬性值預設false,不放棄關係維護
true表示放棄關係維護
-->
<set name="setLinkMan" inverse="true"><!-- cascade="save-update,delete" -->