Hibernate入門(三)—— 一對多、多對多關係

来源:https://www.cnblogs.com/gdwkong/archive/2018/02/11/8337081.html
-Advertisement-
Play Games

本文主要介紹Hibernate如何實現一對多、多對多表,實現相關操作。 ...


一、一對多關係

1.概念

​   一對多關係是關係型資料庫中兩個表之間的一種關係。通常在資料庫層級中,兩表之間是有主外鍵關係的。在ORM中,如何通過對象描述表之間的關係,是ORM核心。

2.Hibernate的一對多關聯映射【重點】

2.1表關係的分析

MySql語句

CREATE TABLE `t_category` (
  `cid` int(11) NOT NULL AUTO_INCREMENT,
  `cname` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`cid`)
);
​
CREATE TABLE `t_product` (
  `pid` int(11) NOT NULL AUTO_INCREMENT,
  `pname` varchar(255) DEFAULT NULL,
  `price` double DEFAULT NULL,
  `cid` int(11) DEFAULT NULL,
  PRIMARY KEY (`pid`),
  KEY `FKq8yr5sflwtcj3jqp58x0oy7lx` (`cid`),
  CONSTRAINT `FKq8yr5sflwtcj3jqp58x0oy7lx` FOREIGN KEY (`cid`) REFERENCES `t_category` (`cid`)
);

2.2創建持久化類

  • Category.java(一的一方)

     1 public class Category {
     2     private Integer cid;
     3     private String cname;
     4     //在一的一方,用一個集合表示和product的關係
     5     private Set<Product> products = new HashSet<Product>();
     6     
     7     public Integer getCid() {
     8         return cid;
     9     }
    10     public void setCid(Integer cid) {
    11         this.cid = cid;
    12     }
    13     public String getCname() {
    14         return cname;
    15     }
    16     public void setCname(String cname) {
    17         this.cname = cname;
    18     }
    19     public Set<Product> getProducts() {
    20         return products;
    21     }
    22     public void setProducts(Set<Product> products) {
    23         this.products = products;
    24     }
    25 }
  • Product.java(多的一方)

     1 public class Product {
     2     private Integer pid;
     3     private String pname;
     4     private double price;
     5     //用一個對象表示,當前商品屬於哪個類別
     6     private Category category;
     7  8     public Integer getPid() {
     9         return pid;
    10     }
    11 12     public void setPid(Integer pid) {
    13         this.pid = pid;
    14     }
    15 16     public String getPname() {
    17         return pname;
    18     }
    19 20     public void setPname(String pname) {
    21         this.pname = pname;
    22     }
    23 24     public double getPrice() {
    25         return price;
    26     }
    27 28     public void setPrice(double price) {
    29         this.price = price;
    30     }
    31 32     public Category getCategory() {
    33         return category;
    34     }
    35 36     public void setCategory(Category category) {
    37         this.category = category;
    38     }
    39     
    40 }
2.3創建映射
  • 分類的映射

    <hibernate-mapping>
        <class name="com.pri.bean.Category" table="t_category">
            <!--一,主鍵屬性  -->
            <id name="cid" column="cid">
                <generator class="native"></generator>
            </id>
            <!-- 二,其它屬性 -->
            <property name="cname" column="cname"/>
        
            <!-- 三,表示和商品的關係 -->
            <!--3.1 set標簽的name屬性:多的一方的集合的名字  -->
            <set name="products">
                <!--3.2 key的 column表示多的一方外鍵名 -->
                <key column="cid"/>
                <!--3.3 one-to-many的class屬性表示多的一方類的全限定名  -->
                <one-to-many class="com.pri.bean.Product"/>
            </set>
        </class>
    </hibernate-mapping>
  • 商品的映射

    <hibernate-mapping>
        <class name="com.pri.bean.Product" table="t_product">
            <!--一,主鍵屬性  -->
            <id name="pid" column="pid">
                <generator class="native"></generator>
            </id>
            <!-- 二,其它屬性 -->
            <property name="pname" column="pname"/>
            <property name="price" column="price"/>
        
            <!-- 三,表示和分類的關係 -->
            <!--3.1name:一的一方對象的名字
                  class: 一的一方類的全限定名
                  column:外鍵的名字
              -->
            <many-to-one name="category" class="com.pri.bean.Category" column="cid"/>
        </class>
    </hibernate-mapping>
2.4將映射添加到配置文件
<!-- 三、載入映射關係配置 -->
<mapping resource="com/pri/bean/Product.hbm.xml"/>
<mapping resource="com/pri/bean/Category.hbm.xml"/>

2.5寫代碼測試

  • TestDb

    public class TestDb {
        
        @Test
        public void fun01(){
            Session session = HibernateUtils.openSession();
             Transaction transaction = session.beginTransaction();
           
             transaction.commit();
             session.close();
        }
    ​
    }

3.級聯操作

3.1概念

​   如果我們對某一個表進行了操作,那麼也會順帶對關聯表進行操作。或者說當對主對象進行某種操作時是也對其關聯的從對象也作類似的操作.

​   eg:如果我們刪除了一個公司,那麼就得要求,員工表也得把屬於這個公司的所有員工也刪除掉。

​   如果我們刪除了一個類別, 那麼該類別下的商品是否要刪除或者不刪除只刪除外鍵,那麼這樣的操作就屬於級聯操作了.

3.2 級聯保存和修改
3.2.1 操作一方級聯保存多方【掌握】
  • 保存Category(一的一方)的時候級聯保存Product(多的一方)

  • 應用場景: 保存一方的同時也需要保存多方(並且多方的數據比較多). eg: 訂單和訂單項

  • <!-- 三、表示和商品的關係 -->
    <!-- 3.1 set標簽的name屬性:多的一方的集合的名字 -->
    <set name="products" cascade="save-update"/>
        <!-- 3.2 key的column表示多的一方外鍵名 -->
        <key column="cid"/>
        <!-- 3.3 one-to-many的class屬性表示多的一方類的全限定名 -->
        <one-to-many class="com.pri.bean.Product"/>
    </set>
 1    /**
 2     * 只保存分類,通過級聯把當前分類下的商品也保存
 3      * 配置: 在category.hbm.xml下設置:
 4      *      <set cascade="save-update">
 5      */
 6     @Test
 7     public void fun02(){
 8         Session session = HibernateUtils.openSession();
 9         Transaction transaction = session.beginTransaction();
10         
11         Category c1 = new Category();
12         c1.setCname("水果");
13         
14         Product p1 = new Product();
15         p1.setPname("蘋果");
16         p1.setPrice(5);
17         
18         //c1和p1 產生關係
19         c1.getProducts().add(p1);
20         //p1和c1產生關係
21         p1.setCategory(c1);
22         session.save(c1);
23         //session.save(p1);不需要了,通過級聯保存特性自動保存
24         transaction.commit();
25         session.close();
26     }
3.2.2操作多方級聯保存一方【瞭解】

 

 

 

 

<!--三.表示和分類的關係 -->
<!-- 3.1 name:一的一方對象的名字
        class: 一的一方類的全限定名
        column:外鍵的名字
-->
<many-to-one name="category" class="com.pri.bean.Category" column="cid" cascade="save-update"/>
  • 保存Product(多的一方的)的時候級聯保存Category(一的一方)

     1    /**
     2      * 只保存商品,通過級聯的特性保存商品對應的分類
     3      * 配置: 在product.hbm.xml下設置:
     4      *      <many-to-one cascade="save-update"/>
     5      */
     6     @Test
     7     public void fun03(){
     8         Session session = HibernateUtils.openSession();
     9         Transaction transaction = session.beginTransaction();
    10         
    11         Category c1 = new Category();
    12         c1.setCname("水果");
    13         
    14         Product p1 = new Product();
    15         p1.setPname("蘋果");
    16         p1.setPrice(5);
    17         
    18         //p1和c1發生關係
    19         p1.setCategory(c1);
    20         
    21         session.save(p1);
    22       
    23         //session.save(c1); 不需要了
    24         
    25         transaction.commit();
    26         session.close();
    27     }
3.3級聯刪除
3.3.1刪除一方級聯刪除多方【掌握】
  • 刪除Category(一的一方)的時候級聯刪除Product(多的一方)

  • 場景: 刪除一方的時候確保多方的數據沒有任何用途的時候的才會用. eg: 公司和員工

  • 實際開發裡面很少刪除用戶的數據. 通常用一個欄位標識的

  • <!--  三.表示和商品的關係 -->
    <!-- 3.1 set標簽的name屬性:多的一方的集合的名字 -->
    <set name="products" cascade="delete">
        <!--3.2 key 的column表示多的一方外鍵名 -->
        <key column="cid"/>
        <!-- 3.3 one-to-many的class屬性表示多的一方類的全限定名 -->
        <one-to-many class="com.pri.bean.Product"/>
    </set>
  •  1 @Test
     2 //級聯刪除商品: 刪除id為1的類別,級聯刪除當前類別下的所有商品
     3 //因為刪除的是類別,所有在Category.hbm.xml配置:<set name="products" cascade="delete">
     4 public void fun03(){
     5       Session session = HibernateUtils.getCurrentSession();
     6       Transaction transaction = session.beginTransaction();
     7                  
     8       //先查 id為1的類別
     9       Category category = session.get(Category.class, 1);
    10       session.delete(category);
    11       transaction.commit();
    12 }
3.3.2 刪除多方級聯刪除一方【瞭解】
  • 刪除Product(多的一方)的時候級聯刪除Category(一的一方)

    <!--三.表示和分類的關係 -->
         <!-- 3.1 name:一的一方對象的名字
                 class: 一的一方類的全限定名
                 column:外鍵的名字
         -->
    <many-to-one name="category" class="com.pri.bean.Category" column="cid" cascade="delete"/>
 1    @Test
 2      //級聯刪除分類: 刪除id為1的商品,級聯刪除這個商品所屬的類別(瞭解)
 3      //把當前id為1商品刪除,把這個商品所屬的類別刪除, 商品表裡面該類別其它的商品的記錄的外鍵置為null;
 4      public void fun04(){
 5          Session session = HibernateUtils.getCurrentSession();
 6          Transaction transaction = session.beginTransaction();
 7          
 8          //先查 id為1的類別
 9          Product product = session.get(Product.class, 1);
10          session.delete(product);
11          
12          
13          transaction.commit();
14      }

4.外鍵維護

4.1 雙向關聯產生多餘的SQL語句

​   一旦存在主外鍵關係,那麼外鍵就由雙方對象去維護了, 那麼就會造成對這個外鍵執行了多次操作, 有一次操作其實可以避免的。 也就是說這個外鍵只要讓一個人去維護即可。 外鍵屬於誰,就讓誰去維護。

  • eg:修改產品對應的類別

4.2inverse標簽屬性
4.2.1概念

  inverse:外鍵維護,預設為false。代表一方不去維護多方外鍵。(inverse有反轉的意思)

  外鍵屬於誰, 誰就負責維護.

4.2.2一方的放棄外鍵維護
  • 只能在一的一方放棄外鍵維護

    <set  inverse="true">
        ...
    </set>
  • EG:

  • <!--  三.表示和商品的關係 -->
    <!-- 3.1 set標簽的name屬性:多的一方的集合的名字 -->
    <set name="products" cascade="delete" inverse="true">
        <!--3.2 key 的column表示多的一方外鍵名 -->
        <key column="cid"/>
        <!-- 3.3 one-to-many的class屬性表示多的一方類的全限定名 -->
        <one-to-many class="com.pri.bean.Product"/>
    </set>
 1 /**
 2    * 把蘋果(p1)的類別設置為水果(c2)
 3      * 衣服是(c1)
 4      */
 5     @Test
 6     public void fun02(){
 7         Session session = HibernateUtils.openSession();
 8         Transaction transaction = session.beginTransaction();
 9         //獲得蘋果
10         Product p1 = session.get(Product.class, 1);
11         //獲得食物類別
12         Category c2 = session.get(Category.class, 2);
13         
14         //p1和c2關聯
15         p1.setCategory(c2);
16         //c2和p1關聯
17         c2.getProducts().add(p1);
18         
19         transaction.commit();
20         session.close();
21     }

二、多對多的關係

1.概念

​ 多對多關係是關係資料庫中兩個表之間的一種數據關係,為了維護這種關係,通常會存在一張中間關係表。兩張表都只和關係表間建立主外鍵關係。

2.Hibernate的多對多關聯映射【重點】

2.1表關係的分析

  • MySql語句

2.2創建實體
  • Student.java

     1 public class Student {
     2     
     3     private Integer sid;
     4     private String sname;
     5     
     6     private Set<Course> courses = new HashSet<Course>();
     7  8     public Integer getSid() {
     9         return sid;
    10     }
    11 12     public void setSid(Integer sid) {
    13         this.sid = sid;
    14     }
    15 16     public String getSname() {
    17         return sname;
    18     }
    19 20     public void setSname(String sname) {
    21         this.sname = sname;
    22     }
    23 24     public Set<Course> getCourses() {
    25         return courses;
    26     }
    27 28     public void setCourses(Set<Course> courses) {
    29         this.courses = courses;
    30     }
    31     
    32 33     
    34 }
  • Course.java

     1 public class Course {
     2     
     3     private Integer cid;
     4     private String cname;
     5     
     6     private Set<Student> students = new HashSet<Student>();
     7  8     public Integer getCid() {
     9         return cid;
    10     }
    11 12     public void setCid(Integer cid) {
    13         this.cid = cid;
    14     }
    15 16     public String getCname() {
    17         return cname;
    18     }
    19 20     public void setCname(String cname) {
    21         this.cname = cname;
    22     }
    23 24     public Set<Student> getStudents() {
    25         return students;
    26     }
    27 28     public void setStudents(Set<Student> students) {
    29         this.students = students;
    30     }
    31      
    32 }
2.3創建映射
  • 學生的映射

     1 <hibernate-mapping>
     2     <class name="com.itheima.bean.Student" table="t_student">
     3         <!--一,主鍵屬性  -->
     4         <id name="sid" column="sid">
     5             <generator class="native"></generator>
     6         </id>
     7         <!-- 二,其它屬性 -->
     8         <property name="sname" column="sname"/>
     9     
    10         <!-- 三,表示和課程的關係 -->
    11         <!--3.1 set標簽的name屬性:當前類中集合的名字 
    12                 table:第三方表名
    13              -->
    14         <set name="courses" table="s_c_tab">
    15             <!--3.2 key的 column表示當前類在中間表中的外鍵 -->
    16             <key column="sid" />
    17                 <!--3.3 many-to-many表示多對多關係
    18                     column:表示另一方在中間表中的外鍵
    19                     class:表示另一方類的全限定名
    20               -->
    21             <many-to-many column="cid" class="com.itheima.bean.Course" ></many-to-many>
    22         </set>
    23     </class>
    24 </hibernate-mapping>
  • 課程的映射

     1 <hibernate-mapping>
     2     <class name="com.itheima.bean.Course" table="t_course">
     3         <!--一,主鍵屬性  -->
     4         <id name="cid" column="cid">
     5             <generator class="native"></generator>
     6         </id>
     7         <!-- 二,其它屬性 -->
     8         <property name="cname" column="cname"/>
     9     
    10         <!-- 三,表示和課程的關係 -->
    11         <!--3.1 set標簽的name屬性:當前類中集合的名字  
    12             table:第三方表名
    13         -->
    14         <set name="students" table="s_c_tab">
    15             <!--3.2 key的 column表示當前類在中間表中的外鍵 -->
    16             <key column="cid"/>
    17                 <!--3.3 many-to-many表示多對多關係
    18                     column:表示另一方在中間表中的外鍵
    19                     class:表示另一方類的全限定名
    20               -->
    21             <many-to-many column="sid" class="com.itheima.bean.Student"></many-to-many>
    22         </set>
    23     </class>
    24 </hibernate-mapping>
2.4將映射添加到配置文件
<!-- 三.載入映射關係配置 -->
<mapping resource="com/pri/bean/Student.hbm.xml"/>
<mapping resource="com/pri/bean/Course.hbm.xml"/>

2.5寫代碼測試
  • 保存

     1     /**
     2      * 正常保存
     3      */
     4     @Test
     5     public void fun01(){
     6         Session session = HibernateUtils.openSession();
     7         Transaction transaction = session.beginTransaction();
     8         
     9         Student s1 = new Student();
    10         s1.setSname("張三");
    11         Student s2 = new Student();
    12         s2.setSname("李四");
    13         
    14         Course c1 = new Course();
    
                  
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、前言 接著上一章的內容,繼續js的學習。 二、內容 解析與序列化 ...
  • 緣由 在急速的互聯網時代,原本ie系列的低版本瀏覽器就該淘汰了。可偏偏還是有很多xp系統ie7、8瀏覽器,這有讓網站甚是苦逼。練就了一套新技術,原本以為能大展身手,可卻在ie陣容中認慫了,不得不規規矩矩的寫著老得掉牙的代碼,用著早已塵封的技術。 (註:因為用戶原因可能使用ie7,而非蛋疼要網站支持i ...
  • 一、前言 繼續上一章的內容,繼續今天的Js學習。 二、內容 事件處理程式 事件對象 事件類型 ...
  • 工作流模塊 1.模型管理 :web線上流程設計器、預覽流程xml、導出xml、部署流程 2.流程管理 :導入導出流程資源文件、查看流程圖、根據流程實例反射出流程模型、激活掛起 3.運行中流程:查看流程信息、當前任務節點、當前流程圖、作廢暫停流程、指派待辦人 4.歷史的流程:查看流程信息、流程用時、流 ...
  • 前段時間看了下設計模式 參考,以及head first設計模式,簡要如下 ...
  • #HTMLTestRunner代碼修改參考 微微微笑 的說明,下麵是鏈接,這個已經說的很詳細了 https://www.cnblogs.com/miniren/p/5301081.html (一) 前言 unittest在命令行輸出測試結果。你可能需要生成一個所有測試的執行結果作為報告或者把測試結果 ...
  • (一) Test Suite測試套件 一個測試套件是多個測試或測試用例的集合,是針對被測程式的對應的功能和模塊創建的一組測試,一個測試套件內的測試用例將一起執行。 應用unittest的TestSuites特性,可以將不同的測試組成一個邏輯組,然後設置統一的測試套件,並通過一個命令來執行測試。這都是 ...
  • 由於本篇博文的項目都很簡單,所以本次開個特例,本次解析兩個項目,但是都很簡單的 項目一:用socket實現文件傳輸 本項目很簡單,作為小項目的預熱的,前面剛學完socket,這裡馬上又利用socket進行項目開發,難不倒各位 項目要求: 1.用socket完成文件上傳功能 2.文件位置可以設置 3. ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...