詳談Hibernate框架關係映射!

来源:http://www.cnblogs.com/liujiayun/archive/2016/08/12/5763290.html
-Advertisement-
Play Games

接觸Hibernate也有一小段的時間了,愈發的覺得Hibernate是個神奇的東西,為什麼這麼說呢?因為你可以不懂一行sql,直接面向對象,就可以將數據直接保存到資料庫去!! 你還可以保存一個對象,然後一次性的將與它相關的所有數據保存到資料庫,比如說,你只需要保存班級對象,就可以將該班級信息和該班 ...


接觸Hibernate也有一小段的時間了,愈發的覺得Hibernate是個神奇的東西,為什麼這麼說呢?因為你可以不懂一行sql,直接面向對象,就可以將數據直接保存到資料庫去!!

你還可以保存一個對象,然後一次性的將與它相關的所有數據保存到資料庫,比如說,你只需要保存班級對象,就可以將該班級信息和該班級下的所有學生在資料庫中形成一堆的記錄。

而且都不需要你寫sql!!!

有木有很神奇。。。。反正寶寶我是驚呆了。

下麵就拿具體的代碼實現來講吧~

首先講一個簡單的  單向一對多的案例(以班級和學生作為案例)

眾所周知,Hibernate運用的是一種面向對象的思想,我們想要與資料庫相關聯,首先我們得必須有與之相對應的實體類

比如說,我有一個學生對象和班級對象,分別對應資料庫中的學生表和班級表具體信息如下:

package entity;
/*
*學生表 
*/ import java.io.Serializable;
public class Student implements Serializable { private Integer sid;//學生編號 private String sname;//學生姓名 private String sex;//學生性別 public Student() { } public Student(String sname, String sex) { this.sname = sname; this.sex = sex; } public Integer getSid() { return sid; } public void setSid(Integer sid) { this.sid = sid; } public String getSname() { return sname; } public void setSname(String sname) { this.sname = sname; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } }

 

package entity;
/*
*班級表
*/
import java.io.Serializable;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class Grade implements Serializable {
    private Integer gid;//班級編號
    private String gname;//班級名稱
    private String gdesc;//班級描述
    
    public Grade() {
    }
    
    public Grade(String gname, String gdesc) {
        this.gname = gname;
        this.gdesc = gdesc;
    }

    public Integer getGid() {
        return gid;
    }
    public void setGid(Integer gid) {
        this.gid = gid;
    }
    public String getGname() {
        return gname;
    }
    public void setGname(String gname) {
        this.gname = gname;
    }
    public String getGdesc() {
        return gdesc;
    }
    public void setGdesc(String gdesc) {
        this.gdesc = gdesc;
    }
    
    
}

 

一對多的話,應該是比較好理解的,因為我們可以理解為   一個班級可以以對應多個學生,這就是一對多,既然一個班級對應多個學生的話,那麼我們是不是就可以在班級的實體類

中加入一個學生集合和呢?這樣是不是更能體現出一對多的關係呢?所以我們對班級實體就有了下麵的改造

package entity;

import java.io.Serializable;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class Grade implements Serializable {
    private Integer gid;//年級編號
    private String gname;//年級名稱
    private String gdesc;//年級描述
    //添加一個班級里的學生集合
    private Set<Student> stus=new HashSet<Student>();

    public Set<Student> getStus() {
        return stus;
    }

    public void setStus(Set<Student> stus) {
        this.stus = stus;
    }

    public Grade() {
    }
    
    public Grade(String gname, String gdesc) {
        this.gname = gname;
        this.gdesc = gdesc;
    }

    public Integer getGid() {
        return gid;
    }
    public void setGid(Integer gid) {
        this.gid = gid;
    }
    public String getGname() {
        return gname;
    }
    public void setGname(String gname) {
        this.gname = gname;
    }
    public String getGdesc() {
        return gdesc;
    }
    public void setGdesc(String gdesc) {
        this.gdesc = gdesc;
    }
    
    
}

 

實體類寫完了,我們就該寫最關鍵的配置文件也就是映射文件了(Grade.hbm.xml)

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- 對應所在的包 -->
<hibernate-mapping package="entity">
    <!-- 實體類和數據表的名稱 -->
    <class name="Grade" table="Grade">
        <!-- 實體類中和數據表中所對應的主鍵 -->
        <id name="gid" column="gid">
            <!-- 主鍵生成策略  increment是值找到最大的主鍵 值,並加1 -->
            <generator class="increment" />
        </id>
        <!-- 非主鍵屬性的配置 -->
        <property name="gname" column="gname" />
        <property name="gdesc"  column="gdesc"/>
        
        <!-- 配置多對一配置信息   -->
        <set name="stus" table="Student" >
            <!-- 多方的外建值 -->
            <key column="gid"></key>
            <one-to-many class="entity.Student"/>
        </set>
    </class>
</hibernate-mapping>

 

這樣我們就完成了一對多的配置了,此時,我們不用對Student.hbm.xml做任何操作,下麵可以測試了

//單向一對多案例(一個班級對應多個學生)
    public static void DOneToManyAdd(){
        //準備session 
        Session session=HibernateUtil.currentSession();
        //開啟事務
        Transaction tx = session.beginTransaction();
        //創建一個班級
        Grade grade=new Grade("S1261","無敵的Y1261班");
        //準備幾個學生
        Student stu1=new Student("微熱的雪","");
        Student stu2=new Student("巴黎的雨季","");
        //設置班級里的學生
        grade.getStus().add(stu1);
        grade.getStus().add(stu2);
        
        //保存
        session.save(grade);
        session.save(stu1);
        session.save(stu2);
        
        //提交事務
        tx.commit();
        //關閉連接
        HibernateUtil.closeSession();
    }

 

執行這些代碼後可以在控制台看到如下信息

這個時候,你的資料庫中便有瞭如下信息

 

可以從上面的測試代碼中看出,我並沒有手動的指定學生所在的班級,但是因為有映射文件,Hibernate會自動的檢索到所在的班級並自行的發送sql語句到資料庫進行持久化操作。

這就是Hibernate的強大之處,當然,這隻是一個最簡單的例子,下麵就跟著我看看更加有趣的例子吧!

 

 Hibernate關係映射二之   單向多對一關係映射

多對一關係映射也同樣的好理解,比如,多個學生可以同時處於一個班級下,這就是單向的多對一的關係,所以我們就可以想到在學生表中加入一個班級屬性

package entity;

import java.io.Serializable;

public class Student implements Serializable {
    private Integer sid;//學生編號
    private String sname;//學生姓名
    private String sex;//學生性別
    //創建一個班級
    private Grade grade;

    public Grade getGrade() {
        return grade;
    }

    public void setGrade(Grade grade) {
        this.grade = grade;
    }

    public Student() {
    }
    
    public Student(String sname, String sex) {
        this.sname = sname;
        this.sex = sex;
    }

    public Integer getSid() {
        return sid;
    }
    public void setSid(Integer sid) {
        this.sid = sid;
    }
    public String getSname() {
        return sname;
    }
    public void setSname(String sname) {
        this.sname = sname;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    
    
}

 

 因為是單向的多對一,所以我們只需要在多的一方,也就是學生方的配置文件中進行修改,班級方的配置文件保持原始(也就是沒有set標簽的時候)

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="entity">
    <class name="Student" table="Student">
        <id name="sid" column="sid">
            <generator class="increment" />
        </id>
        <property name="sname" column="sname" />
        <property name="sex"  column="sex"/>
        <!-- 配置多對一的關係映射 -->
        <many-to-one name="grade" class="entity.Grade" column="gid"></many-to-one>
    </class>
</hibernate-mapping>

 

同樣,我們做一個單向多對一的添加操作

//單向多對一添加案例(多個學生對應一個班級)
    public static void DManyToOneAdd(){
        //準備session 
        Session session=HibernateUtil.currentSession();
        //開啟事務
        Transaction tx = session.beginTransaction();
        //創建一個班級
        Grade grade=new Grade("S2222班","挺6的S2222班");
        //準備幾個學生
        Student stu1=new Student("恩恩","");
        Student stu2=new Student("呵呵","");
        //設置學生所在的班級
        stu1.setGrade(grade);
        stu2.setGrade(grade);
        //保存
        session.save(grade);
        session.save(stu1);
        session.save(stu2);
        //提交事務
        tx.commit();
        //關閉連接
        HibernateUtil.closeSession();
    }

 

註意!!!此時的Hibernate生成的sql語句與一對多時是不一樣的!

資料庫中同樣也是有相對應的記錄

 

經過上面兩個案例的展示,可能有同學就會有疑問了,既然多個學生可以屬於一個班級,一個班級又可以有多個學生,那麼他們倆之間到底可以設為 什麼關係呢?

此時,我們就可以設置為  雙向的一對多的關係了。因為班級和學生是一個雙向的關係,而且一個班級又有多個學生

這時我們完整的配置文件就是以上的兩個總和了

Student.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="entity">
    <class name="Student" table="Student">
        <id name="sid" column="sid">
            <generator class="increment" />
        </id>
        <property name="sname" column="sname" />
        <property name="sex"  column="sex"/>
        <!-- 配置多對一的關係映射 -->
        <many-to-one name="grade" class="entity.Grade" column="gid" ></many-to-one>
    </class>
</hibernate-mapping>

 

Grade.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- 對應所在的包 -->
<hibernate-mapping package="entity">
    <!-- 實體類和數據表的名稱 -->
    <class name="Grade" table="Grade">
        <!-- 實體類中和數據表中所對應的主鍵 -->
        <id name="gid" column="gid">
            <!-- 主鍵生成策略  increment是值找到最大的主鍵 值,並加1 -->
            <generator class="increment" />
        </id>
        <!-- 非主鍵屬性的配置 -->
        <property name="gname" column="gname" />
        <property name="gdesc"  column="gdesc"/>
        
        <!-- 配置多對一配置信息   -->
        <set name="stus" table="Student"  >
            <!-- 多方的外建值 -->
            <key column="gid"></key>
            <one-to-many class="entity.Student"/>
        </set>
    </class>
</hibernate-mapping>

 

測試數據

//雙向添加案例
    private static void SAdd(){
        //準備session 
        Session session=HibernateUtil.currentSession();
        //開啟事務
        Transaction tx = session.beginTransaction();
        //創建一個班級
        Grade grade=new Grade("S2222班","挺6的S2222班");
        //準備幾個學生
        Student stu1=new Student("巴黎的雨季","");
        Student stu2=new Student("微熱的雪","");
        //設置班級下的學生
        grade.getStus().add(stu1);
        grade.getStus().add(stu2);
        //為學生設置班級
        stu1.setGrade(grade);
        stu2.setGrade(grade);
        //保存
        session.save(grade);
            session.save(stu1);
        session.save(stu2);
        //提交事務
        tx.commit();
        
        //關閉連接
        HibernateUtil.closeSession();
    }

 

細心的同學會發現,當我執行了上面的代碼時,效果與我設置多對一和一對多的效果一樣,而且這還比較的繁瑣和複雜,所以這並不是雙向關係的優勢

這裡我們就要用到cascade(級聯)的屬性了   設置級聯的屬性後,因為有 雙向的關係,所以當你只添加班級的時候Hibernate會自動的添加班級下的學生

Student.hbm.xml

 

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="entity">
    <class name="Student" table="Student">
        <id name="sid" column="sid">
            <generator class="increment" />
        </id>
        <property name="sname" column="sname" />
        <property name="sex"  column="sex"/>
        <!-- 配置多對一的關係映射 -->
        <many-to-one name="grade" class="entity.Grade" column="gid" cascade="all"></many-to-one>
    </class>
</hibernate-mapping>

 

Grade.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- 對應所在的包 -->
<hibernate-mapping package="entity">
    <!-- 實體類和數據表的名稱 -->
    <class name="Grade" table="Grade">
        <!-- 實體類中和數據表中所對應的主鍵 -->
        <id name="gid" column="gid">
            <!-- 主鍵生成策略  increment是值找到最大的主鍵 值,並加1 -->
            <generator class="increment" />
        </id>
        <!-- 非主鍵屬性的配置 -->
        <property name="gname" column="gname" />
        <property name="gdesc"  column="gdesc"/>
        
        <!-- 配置多對一配置信息   -->
        <set name="stus" table="Student" cascade="all" inverse="true">
            <!-- 多方的外建值 -->
            <key column="gid"></key>
            <one-to-many class="entity.Student"/>
        </set>
    </class>
</hibernate-mapping>

 

 這樣當我們設置級聯的屬性後,測試代碼如下

//雙向添加案例(添加班級自動添加班級下的學生)
    private static void SAdd(){
        //準備session 
        Session session=HibernateUtil.currentSession();
        //開啟事務
        Transaction tx = session.beginTransaction();
        //創建一個班級
        Grade grade=new Grade("S2222班","挺6的S2222班");
        //準備幾個學生
        Student stu1=new Student("巴黎的雨季","");
        Student stu2=new Student("微熱的雪","");
        //設置班級下的學生
        grade.getStus().add(stu1);
        grade.getStus().add(stu2);
        //為學生設置班級
        stu1.setGrade(grade);
        stu2.setGrade(grade);
        //保存(設置級聯屬性,自動關聯該班級下的學生)
        session.save(grade);
    
        
        //提交事務
        tx.commit();
        
        //關閉連接
        HibernateUtil.closeSession();
    }

 

這樣,我們只用寫save(grade) 保存班級,這時Hibernate會生成如下代碼

至此,基本上就講完了Hibernate中單向關係映射的知識點了,明天為大家講解關於雙向多對多關係映射的知識點。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1.tomcat7-maven-plugin插件 1. 不通過外部的tomcat 直接將tomcat核心內嵌在項目中,tomcat7:run 命令就可以啟動項目,可以直接訪問 localhost:8080/Demo 2. 熱部署(tomcat是活的) tomcat7:deploy 命令就可以將項目發 ...
  • 設計一個小型的記憶體池以及鏈表 上一節擼到萬事俱備只欠真正的 , 但是 的作用是將源代碼轉化為 流, 用什麼保存 ? 這就涉及到我們要接觸的第一個數據結構—鏈表, 雖然標準庫中很多容器都可以承擔鏈表的任務, 但是我說過 出於鍛煉原因, 我會儘量不使用stl中的容器 , 所以我決定自己擼一個鏈表出來, ...
  • 今天來說說圖片壓縮技術,為什麼要使用圖片壓縮,圖片上傳不就完事了嗎?對的,這在幾年前可以這麼說,因為幾年前還沒有現在這麼大的併發,也沒有現在這麼關註性能。 如今手機很多,很多人都是通過手機訪問網路或者app,再調用介面的時候肯定會多多少少的瀏覽圖片,尤其是脫離wifi的情況下,可以看到很多軟體展示都 ...
  • 一、轉向(Forward) 1.要點說明 轉向是通過RequestDispatcher對象的forward()方法來實現的。RequestDispatcher可以通過HttpServletRequest的getRequestDispatcher()方法獲得。getRequestDispatcher( ...
  • Go語言是Google內部主推的語言,它作為一門全新的靜態類型開發語言,與當前的開發語言相比具有許多令人興奮不已的新特性。專門針對多處理器系統的應用程式編程進行了優化,使用go語言完全可以媲美c、c++的速度,而且更加安全、簡潔,支持並行進程。 以下是go語言的主要特性: 1、自動垃圾回收 2、更豐 ...
  • --> Poker類用於存入54張撲克牌 --> Player類對玩家進行發牌和顯示處理(寫完我就後悔了,J,Q,K,A,2的排序太low了..package com.dragon.java.hwddz; --> 寫完發現邏輯是不是有問題啊... ...
  • 定義: 單來源調用指一個類的生成工作只能由特定類來執行。 eg李寧牌鞋子只能由李寧專賣店生產 這個問題歸結起來,也就是說在工廠模式中,指定的產品類只能通過具體的特定工廠類來生成,而不能自己new出來或者通過其他類生成。 具體的,我們就在代碼實現中進行說明瞭。 這裡我們來一步一步分析。 首先,一個類實 ...
  • 昨天跟大家分享了Hibernate中單向的一對多、單向多對一、雙向一對多的映射關係,今天跟大家分享下在Hibernate中雙向的多對多的映射關係 這次我們以項目和員工舉個慄子,因為大家可以想象得到,在真實的環境下,一個項目肯定是對應著多個員工的,這毫無疑問, 那麼同時,一個比較牛員工也能同時參與多個 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...