Hibernate 一對多操作

一 表與表之間關系回顧

  • 一對多
  • 多對多
  • 一對一

二 hibernate一對多操作
1 一對多映射配置
以客戶聯系人為列:客戶是一,聯系人是多
(1)創建兩個實體類,一個客戶,一個聯系人 
Customer.java

package entity;

import java.util.HashSet;
import java.util.Set;

public class Customer {
    private Integer cid;
    private String custName;
    private String custLevel;
    private String custSource;
    private String custPhone;
    private String custMobile;
    // 在客戶類里面表示多個聯系人,一個客戶有多個聯系人
    //在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 getCustName() {
        return custName;
    }

    public void setCustName(String custName) {
        this.custName = custName;
    }

    public String getCustLevel() {
        return custLevel;
    }

    public void setCustLevel(String custLevel) {
        this.custLevel = custLevel;
    }

    public String getCustSource() {
        return custSource;
    }

    public void setCustSource(String custSource) {
        this.custSource = custSource;
    }

    public String getCustPhone() {
        return custPhone;
    }

    public void setCustPhone(String custPhone) {
        this.custPhone = custPhone;
    }

    public String getCustMobile() {
        return custMobile;
    }

    public void setCustMobile(String custMobile) {
        this.custMobile = custMobile;
    }
}

LinkMan.java

package entity;

public class LinkMan {
    private Integer lkm_id;
    private String lkm_name;
    private String lkm_gender;
    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_name() {
        return lkm_name;
    }

    public void setLkm_name(String lkm_name) {
        this.lkm_name = lkm_name;
    }

    public String getLkm_gender() {
        return lkm_gender;
    }

    public void setLkm_gender(String lkm_gender) {
        this.lkm_gender = lkm_gender;
    }

    public String getLkm_phone() {
        return lkm_phone;
    }

    public void setLkm_phone(String lkm_phone) {
        this.lkm_phone = lkm_phone;
    }
}

(2)讓實體類之間互相進行表示

  • 在客戶實體類里面有多個聯系人

    • 一個客戶里面有多個聯系人
  • 在聯系人實體類里面表示所屬客戶

    • 一個聯系人只能屬于一個客戶

(3)配置映射文件

  • 一般一個實體類對應一個映射文件
    Customer.hb,.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="entity.Customer" table="t_customer">
        <id name="cid" column="cid">
        <generator class="native"></generator>
        </id>
        <property name="custLevel" column="custLevel"></property>
        <property name="custMobile" column="custMobile"></property>
        <property name="custName" column="custName"></property>
        <property name="custPhone" column="custPhone"></property>
        <property name="custSource" column="custSource"></property>
        <!--在客戶映射文件中,表示所有聯系人
        使用set標簽表示所有聯系人
        set標簽里面有name屬性,屬性值寫在客戶實體類里面表示聯系人的set集合
        -->
        <set name="setlinkMan">
            <!--一對多建表,有外鍵
            hibernate機制:雙向維護外鍵,在一和多那一方配置外鍵
            column屬性值:外鍵名稱-->
            <key column="clid"></key>
            <!--客戶所有聯系人,class里面寫聯系人實體類全路徑-->
            <one-to-many class="entity.LinkMan"></one-to-many>
        </set>

    </class>
</hibernate-mapping>

LinkMan.hbm.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="entity.LinkMan" table="t_linkman">
        <id name="lkm_id" column="lkm_id">
            <generator class="native"></generator>
        </id>
        <property name="lkm_name" column="lkm_name"></property>
        <property name="lkm_gender" column="lkm_gender"></property>
        <property name="lkm_phone" column="lkm_phone"></property>
        <!--表示聯系人所屬客戶
        name:因為聯系人在實體類使用customer對象表示,寫customer名稱
        class:customer全路徑
        column:外鍵名稱
        -->
        <many-to-one name="customer" class="entity.Customer" column="clid"></many-to-one>
    </class>
    

</hibernate-mapping>
  • 把映射最基本配置完成
  • 在映射文件中,配置一對多的關系
    • 在客戶映射文件中,表示所有聯系人
        <!--在客戶映射文件中,表示所有聯系人
        使用set標簽表示所有聯系人
        set標簽里面有name屬性,屬性值寫在客戶實體類里面表示聯系人的set集合
        -->
        <set name="setlinkMan">
            <!--一對多建表,有外鍵
            hibernate機制:雙向維護外鍵,在一和多那一方配置外鍵
            column屬性值:外鍵名稱-->
            <key column="clid"></key>
            <!--客戶所有聯系人,class里面寫聯系人實體類全路徑-->
            <one-to-many class="entity.LinkMan"></one-to-many>
        </set>
  • 在聯系人映射文件中,表示所屬客戶
        <!--表示聯系人所屬客戶
        name:因為聯系人在實體類使用customer對象表示,寫customer名稱
        class:customer全路徑
        column:外鍵名稱
        -->
        <many-to-one name="customer" class="entity.Customer" column="clid"></many-to-one>

(4)創建核心配置文件

        <mapping resource="Customer.hb,.xml"></mapping>
        <mapping resource="LinkMan.hbm.xml"></mapping>
測試結果
數據表創建成功

2 一對多級聯操作
(1)級聯操作

  • 級聯保存
    添加一個客戶,為這個客戶添加多個聯系人
  • 級聯刪除
    刪除某一給我客戶,這個客戶里面的所有的聯系人也刪除

(2)一對多級聯保存
目標:添加客戶,為這個客戶添加一個聯系人
方法一:

import Utils.HibernateUtils;
import entity.Customer;
import entity.LinkMan;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

public class HibernateOnetoMany {
    //演示一對多級聯保存
    @Test
    public void testAddDemo1(){
        Transaction tx = null;
        try{
          Session session =  HibernateUtils.getSessionObject();
          tx= session.beginTransaction();
            //添加一個客戶,為這個客戶添加一個聯系人
            //1 創建客戶和聯系人對象
            Customer customer = new Customer();
            customer.setCustName("歐亞學院");
            customer.setCustLevel("VIP");
            customer.setCustSource("軟工");
            customer.setCustPhone("13692127465");
            customer.setCustMobile("029864564");

            LinkMan linkMan = new LinkMan();
            linkMan.setLkm_name("楊某人");
            linkMan.setLkm_gender("男");
            linkMan.setLkm_phone("130****3381");
            //2 在客戶表示聯系人,在聯系人表示客戶,建立客戶對象和聯系人對象關系
            //2.1 把聯系人對象放到客戶對象的set集合里面
            customer.getSetlinkMan().add(linkMan);
            //2.2 把客戶對象放到聯系人里面去
            linkMan.setCustomer(customer);
            //3 保存到數據庫
            session.save(customer);
            session.save(linkMan);
          tx.commit();
        }catch (Exception e){
            e.printStackTrace();
            tx.rollback();
        }
    }
}

聯系人表
客戶表

方法二
一般根據客戶添加聯系人
第一步 在客戶映射文件中添加配置

  • 在客戶映射文件中有set標簽進行配置
配置

第二步 創建客戶和聯系人對象,只需要把聯系人放到客戶里面就可以了,最終只需要保存客戶就可以了

public void testAddDemo2(){
        Transaction tx = null;
        try{
           Session session= HibernateUtils.getSessionObject();
           tx = session.beginTransaction();
            //1 創建客戶和聯系人對象
            Customer customer = new Customer();
            customer.setCustName("百度");
            customer.setCustLevel("普通用戶");
            customer.setCustSource("網絡");
            customer.setCustPhone("13612227465");
            customer.setCustMobile("021864564");

            LinkMan linkMan = new LinkMan();
            linkMan.setLkm_name("陳某人");
            linkMan.setLkm_gender("女");
            linkMan.setLkm_phone("130315245456");
            //2 把聯系人放到客戶里面
            customer.getSetlinkMan().add(linkMan);
            //3 保存
            session.save(customer);
           tx.commit();
        }catch (Exception e){
            e.printStackTrace();
            tx.rollback();
        }
    }
聯系人表
客戶表

(3)級聯刪除
需求:刪除某個客戶,把客戶里面所有的聯系人刪除
實現:
第一步 在客戶映射文件set標簽,進行配置

配置

第二步 在代碼中直接刪除客戶(根據id查詢對象,調用session里面delete方法刪除)

 public void testDelDemo3(){
        Transaction tx = null;
        try{
             Session session= HibernateUtils.getSessionObject();
             tx = session.beginTransaction();
            Customer customer= session.get(Customer.class,1);
            session.delete(customer);
             tx.commit();
        }catch (Exception e){
            e.printStackTrace();
            tx.rollback();
        }
    }
用戶表
聯系人表

執行過程:

  • 根據id查詢客戶
第一步
  • 根據外鍵id值查詢聯系人
第二步
  • 把聯系人的外鍵設置外null
第三步
  • 刪除聯系人和客戶
第四步

(4)一對多修改操作
需求:讓陳某人聯系人所屬客戶不屬于百度,而是歐亞

    @Test
    public void testUpdateDemo4(){
        Transaction tx = null;
        try {
           Session session = HibernateUtils.getSessionObject();
           tx = session.beginTransaction();
            //1 根據id查詢陳某人,根據id查百度的客戶
            Customer eurasia= session.get(Customer.class,1);
           LinkMan chen = session.get(LinkMan.class,2);
           //2 設置持久態對象
            //把聯系人放到客戶里面
            eurasia.getSetlinkMan().add(chen);
            //把客戶放到聯系人里面
            chen.setCustomer(eurasia);
            
           tx.commit();
        }catch (Exception e){
            e.printStackTrace();
            tx.rollback();
        }
    }
數據庫

(5)inverse屬性

  • 因為hibernate雙向維護外鍵,在客戶和聯系人里面都需要維護外鍵,修改客戶時候修改一次外鍵,修改聯系人時候也修改一次外鍵,造成效率問題。
外鍵修改
  • 解決方式:讓其中一方不維護外鍵(一對多里面,讓其中一方放棄外鍵維護)
  • 具體實現:在放棄關系維護映射文件中,進行配置,在set標簽上使用inverse屬性
inverse

說明:inverse屬性默認值,false不放棄關系維護,true表示放棄關系維護

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容