1. 程式人生 > >Hibernate學習(七)

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" -->