Hibernate中的一對一關聯和組件的映射

来源:http://www.cnblogs.com/zhangzongle/archive/2016/08/18/5783080.html
-Advertisement-
Play Games

Hibernate提供了兩種映射一對一映射關聯關係的方式: 01.按照外鍵映射 02.按照主鍵映射 下麵以員工賬號表和員工檔案表(員工賬號和檔案表之間是一對一的關係)為例,介紹這兩種映射關係,並使用這兩種 映射方式分別完成以下持久化操作 (1)保存員工檔案的同時分配給員工一個賬號 (2)載入員工檔案 ...


Hibernate提供了兩種映射一對一映射關聯關係的方式:

01.按照外鍵映射

02.按照主鍵映射

下麵以員工賬號表和員工檔案表(員工賬號和檔案表之間是一對一的關係)為例,介紹這兩種映射關係,並使用這兩種 映射方式分別完成以下持久化操作

(1)保存員工檔案的同時分配給員工一個賬號

(2)載入員工檔案的同時載入賬號信息

一:按照外鍵映射

需要提示:

HibernateUtil工具類(用於獲取session和關閉session)

package cn.zhang.util;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {
    //初始化一個ThreadLocal對象,有get和set方法
    private static final ThreadLocal<Session> sessionTL=new ThreadLocal<Session>();
    
    private static Configuration configuration;
    
    private final static SessionFactory sessionFactory;
    static{
        
        configuration=new Configuration().configure();
        sessionFactory=configuration.buildSessionFactory();
    }
    //獲得session對象
    public static Session currentSession() {
        //sessionTL的get方法根據當前線程返回其對應的線程內部變數,即Session對象,多線程情況下共用資料庫連接是不安全的。
        //ThreadLocal保證了每個線程都有自己的session對象
        Session session=(Session)sessionTL.get();
        if (session==null) {
            session=sessionFactory.openSession();
            sessionTL.set(session);
        }
        
        return session;
    }
    //關閉session對象
    public static void closeSession() {
        Session session=(Session)sessionTL.get();
        sessionTL.set(null);
        session.close();
    }

}

Resume1.java實體類

package cn.zhang.entity;

public class Resume1 {
    
    private Integer resid;
    private String resname;
    private String rescardno;
    private Users1 users1;
    
    public Resume1(String resname, String rescardno) {
        super();
        this.resname = resname;
        this.rescardno = rescardno;
    }
    public Resume1() {
    }
    public Integer getResid() {
        return resid;
    }
    public void setResid(Integer resid) {
        this.resid = resid;
    }
    public String getResname() {
        return resname;
    }
    public void setResname(String resname) {
        this.resname = resname;
    }
    public String getRescardno() {
        return rescardno;
    }
    public void setRescardno(String rescardno) {
        this.rescardno = rescardno;
    }
    public Users1 getUsers1() {
        return users1;
    }
    public void setUsers1(Users1 users1) {
        this.users1 = users1;
    }
    
}
Users1.java實體類
package cn.zhang.entity;

public class Users1 {
    private Integer userid;
    private String username;
    private String userpass;
    private Resume1 resume1;
    
    
    public Users1(String username, String userpass) {
        super();
        this.username = username;
        this.userpass = userpass;
    }
    public Users1() {
    }
    public Integer getUserid() {
        return userid;
    }
    public void setUserid(Integer userid) {
        this.userid = userid;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getUserpass() {
        return userpass;
    }
    public void setUserpass(String userpass) {
        this.userpass = userpass;
    }
    public Resume1 getResume1() {
        return resume1;
    }
    public void setResume1(Resume1 resume1) {
        this.resume1 = resume1;
    }
    
}
Users1.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 package="cn.zhang.entity">
   <class name="Users1" table="USERS1">
     <id name="userid" column="USERID" >
        <generator class="sequence">
                <param name="sequence">SQ_Num</param>
        </generator>
     </id>
     <property name="username" column="USERNAME" type="string"></property>
     <property name="userpass" column="USERPASS" type="string"></property>
     <!-- 一對一關聯 -->
     <!-- property-ref屬性為users1,表明通過Resume1的users1的屬性建立從 Users1對象到Resume1對象的關聯,如果不指定,它會預設兩張表的主鍵聯繫,引發錯誤-->
     <one-to-one name="resume1" class="Resume1" property-ref="users1"></one-to-one>
   </class>
</hibernate-mapping>

Resume1.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 package="cn.zhang.entity">
   <class name="Resume1" table="RESUME1">
     <id name="resid" column="RESID" >
        <generator class="sequence">
                <param name="sequence">SQ_Num</param>
        </generator>
     </id>
     <property name="resname" column="RESNAME" type="string"></property>
     <property name="rescardno" column="RESCARDNO" type="string"></property>
     <!-- 一對一配置 -->
     <!--column="RESUSERID": Resume1對應Users1表的外鍵關係 -->
     <!--unique="true":表明每個Resume1對象都有唯一的Users1對象,確保唯一性-->
     <!--cascade="all":級聯 -->
     <many-to-one name="users1" class="Users1" cascade="all" column="RESUSERID" unique="true"></many-to-one>
   </class>
</hibernate-mapping>

hibernate.cfg.xml大配置文件

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

    <session-factory>

        <!-- Database connection settings -->
        <property name="connection.driver_class">oracle.jdbc.OracleDriver</property>
        <property name="connection.url">jdbc:oracle:thin:@localhost:1521:orcl</property>
        <property name="connection.username">***</property>
        <property name="connection.password">***</property>

        <!-- SQL dialect (SQL 方言)-->
        <property name="dialect">org.hibernate.dialect.Oracle10gDialect</property>
    
        <!-- Drop and re-create the database schema on startup -->
         <property name="hbm2ddl.auto">create</property> 

        <!-- Echo all executed SQL to stdout  在控制台列印後臺的SQL語句-->
        <property name="show_sql">true</property>
        
        <!-- 格式化顯示SQL -->
        <property name="format_sql">true</property>    
        
        <!-- JDBC connection pool (use the built-in) -->
        <!-- <property name="connection.pool_size">1</property> -->
        
        <!-- Enable Hibernate's automatic session context management 指定當前session範圍和上下文-->
        <!--  <property name="current_session_context_class">thread</property> -->
        
        <!-- Disable the second-level cache -->
        <!-- <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>-->

        <mapping resource="cn/zhang/entity/Resume1.hbm.xml" />
        <mapping resource="cn/zhang/entity/Users1.hbm.xml" />
        
    </session-factory>

</hibernate-configuration>

測試類:

/**
     * 一對一關聯測試
     */
    @Test
      public void testOne(){
           Session session = HibernateUtil.currentSession();
           Transaction tx=session.beginTransaction();
           //創建一個用戶對象
           Users1 u1=new Users1("ZhangZong","521");
           //創建一個檔案對象
           Resume1 r1=new Resume1("精英檔案","好");
           u1.setResume1(r1);
           r1.setUsers1(u1);
           //保存r1自動保存u1
           session.save(r1);//以為Resume1設置了級聯,保存r1,u1也會保存
           tx.commit();
           HibernateUtil.closeSession();
           System.out.println("成功");
      }

結果展示:

01.控制台

02.資料庫

 users1表

resume1表

 

二:按照主鍵映射

Users2表的userid欄位是主鍵,同時作為外鍵參照Resume2表的主鍵,即Users2表與Resume2表共用主鍵(Users2中的主鍵值是根據Resume2生成的主鍵值取值的)

需要提示:

 

Resume2實體類:

package cn.zhang.entity;

public class Resume2 {
    private Integer resid;
    private String resname;
    private String rescardno;
    private Users2 users2;
    
    public Resume2(String resname, String rescardno) {
        super();
        this.resname = resname;
        this.rescardno = rescardno;
    }
    public Resume2() {
    }
    public Integer getResid() {
        return resid;
    }
    public void setResid(Integer resid) {
        this.resid = resid;
    }
    public String getResname() {
        return resname;
    }
    public void setResname(String resname) {
        this.resname = resname;
    }
    public String getRescardno() {
        return rescardno;
    }
    public void setRescardno(String rescardno) {
        this.rescardno = rescardno;
    }
    public Users2 getUsers2() {
        return users2;
    }
    public void setUsers2(Users2 users2) {
        this.users2 = users2;
    }
    
}

Users2.java實體類

package cn.zhang.entity;

public class Users2 {
    private Integer userid;
    private String username;
    private String userpass;
    private Resume2 resume2;
    
    
    public Users2(String username, String userpass) {
        super();
        this.username = username;
        this.userpass = userpass;
    }
    public Users2() {
    }
    public Integer getUserid() {
        return userid;
    }
    public void setUserid(Integer userid) {
        this.userid = userid;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getUserpass() {
        return userpass;
    }
    public void setUserpass(String userpass) {
        this.userpass = userpass;
    }
    public Resume2 getResume2() {
        return resume2;
    }
    public void setResume2(Resume2 resume2) {
        this.resume2 = resume2;
    }
    
}

Resume2.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 package="cn.zhang.entity">
   <class name="Resume2" table="RESUME2">
   <!-- 主鍵的生成策略,Users2表中的主鍵userid會根據此來取值 -->
     <id name="resid" column="RESID" >
        <generator class="sequence">
                <param name="sequence">SQ_Num</param>
        </generator>
     </id>
     <property name="resname" column="RESNAME" type="string"></property>
     <property name="rescardno" column="RESCARDNO" type="string"></property>
     <!-- 一對一配置 -->
     <one-to-one name="users2" class="Users2" cascade="all"></one-to-one>
   </class>
</hibernate-mapping>

Users2.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 package="cn.zhang.entity">
   <class name="Users2" table="USERS2">
   <!-- foreign生成策略,根據Resume2的主鍵生成策略 -->
     <id name="userid" column="USERID" >
         <generator class="foreign">
          <param name="property">resume2</param>
        </generator>
     </id>
     <property name="username" column="USERNAME" type="string"></property>
     <property name="userpass" column="USERPASS" type="string"></property>
     <!-- 一對一關聯 -->
     <!--constrained="true":表明 Users2表的userid主鍵同時作為外鍵參照Resume2表的主鍵-->
     <one-to-one name="resume2" class="Resume2" constrained="true"></one-to-one>
   </class>
</hibernate-mapping>

測試:

/**
     * 一對一關聯測試:按照主鍵映射
     */
    @Test
      public void testOne(){
           Session session = HibernateUtil.currentSession();
           Transaction tx=session.beginTransaction();
           //創建一個用戶對象
           Users2 u1=new Users2("ZhangZong","521");
           //創建一個檔案對象
           Resume2 r1=new Resume2("精英檔案","好");
           u1.setResume2(r1);
           r1.setUsers2(u1);
           //保存r1自動保存u1
           session.save(r1);
           tx.commit();
           HibernateUtil.closeSession();
           System.out.println("成功");
      }

結果展示:

01.控制台

 

02.資料庫

Resume2表

Users2表

 三:組件的映射

建立關係數據模型的一個重要原則是在不會導致數據冗餘的前提下,儘可能減少資料庫表中的數目及表之間的外鍵參照關係。以員工信息為例,員工信息中有員工的家庭地址信息,如果把地址信息單獨放在一張表中,然後建立員工信息表和地址信息表之間的外鍵關係,當每次查詢員工信息時,都需要建立這兩個表的連接。建立表的連接是很耗時的操作,為了提高資料庫運行性能,可以把這兩張表的信息整合在一張員工信息表Empinfo中

 

需要提示:

 

EmpHomeAddress.java實體類

package cn.zhang.entity;
//員工地址信息實體類
public class EmpHomeAddress {
    private String ehomestreet;
    private String ehomecity;
    private String ehomeprovince;
    private String ehomezipcode;
    private EmpInfo empinfo;
    public String getEhomestreet() {
        return ehomestreet;
    }
    public void setEhomestreet(String ehomestreet) {
        this.ehomestreet = ehomestreet;
    }
    public String getEhomecity() {
        return ehomecity;
    }
    public void setEhomecity(String ehomecity) {
        this.ehomecity = ehomecity;
    }
    public String getEhomeprovince() {
        return ehomeprovince;
    }
    public void setEhomeprovince(String ehomeprovince) {
        this.ehomeprovince = ehomeprovince;
    }
    public String getEhomezipcode() {
        return ehomezipcode;
    }
    public void setEhomezipcode(String ehomezipcode) {
        this.ehomezipcode = ehomezipcode;
    }
    public EmpInfo getEmpinfo() {
        return empinfo;
    }
    public void setEmpinfo(EmpInfo empinfo) {
        this.empinfo = empinfo;
    }
    

}

EmpInfo.java實體類

package cn.zhang.entity;
//員工實體類
public class EmpInfo {
    private Integer eid;
    private String ename;
    private EmpHomeAddress ehome;//地址信息
    public Integer getEid() {
        return eid;
    }
    public void setEid(Integer eid) {
        this.eid = eid;
    }
    public String getEname() {
        return ename;
    }
    public void setEname(String ename) {
        this.ename = ename;
    }
    public EmpHomeAddress getEhome() {
        return ehome;
    }
    public void setEhome(EmpHomeAddress ehome) {
        this.ehome = ehome;
    }
    

}

EmpInfo.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 package="cn.zhang.entity">
   <class name="EmpInfo" table="EMPINFO">
       <id name="eid" column="EID">
        <generator class="native"></generator>
       </id>
       <property name="ename" column="ENAME" type="string"></property>
       <!--組件的映射配置 -->
       <!--component元素表明 ehome屬性是EmpInfo類的一個組成部分
            name設定被映射的持久化類的屬性名       
       -->       
       <component name="ehome" class="EmpHomeAddress">
       <!-- parent指定EmpHomeAddress類所屬的整體類 -->
          <parent name="empinfo"/>
          <!-- 基本映射 -->
          <property name="ehomestreet" column="EHOMESTREET" type="string"></property>
          <property name="ehomecity" column="EHOMECITY" type="string"></property>
          <property name="ehomeprovince" column="EHOMEPROVINCE" type="string"></property>
          <property name="ehomezipcode" column="EHOMEZIPCODE" type="string"></property>
       </component>
   </class> 
</hibernate-mapping>

測試類:

/**
     * 組件的映射測試
     */
    @Test
      public void testOne(){
           Session session = HibernateUtil.currentSession();
           Transaction tx=session.beginTransaction();
           //創建一個員工對象
           EmpInfo emp=new EmpInfo();
           emp.setEname("張總");
           
           //創建一個員工地址對象
           EmpHomeAddress address=new EmpHomeAddress();
           address.setEhomecity("北京");
           address.setEhomeprovince("北京");
           address.setEhomestreet("五道口");
           address.setEhomezipcode("100000");
           address.setEmpinfo(emp);
           emp.setEhome(address);
           session.save(emp);
           tx.commit();
           HibernateUtil.closeSession();
           System.out.println("成功");
      }

測試結果展示:

01.控制台

 

02.資料庫

EMPINFO表:

 

 

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

-Advertisement-
Play Games
更多相關文章
  • 信鴿推送官方sdk沒提供C#版的DEMO,考慮到應該有其他.NET的也會用到信鴿,下麵是我在使用信鴿過程中寫的demo。有什麼不對的地方,歡迎各位大牛指導。 ...
  • 今天學的新東西是WPF的模板,以後會學習更多關於WPF的東東的 ...
  • jquery easyui使用(四)······添加,編輯,刪除 ...
  • 警告:這是一個入門級日誌,如果你很瞭解CodeFirst,那請繞道 背景:這篇日誌記錄我使用Entity FrameWork CodeFirst時出現的錯誤和解決問題的過程,雖然有點曲折……勿噴 備註:這確實算是Entity FrameWork CodeFirst的問題個人也不知道應該給文章加什麼樣 ...
  • 本文想通過配置VS Code來實現對AngularJS的智能提示。在一般的情況下對於在HTML頁面是支持提示的。但是在js頁面就不是很友好,它是記憶你之前的輸入,要是之後有重覆的輸入,VS Code會提示您,僅此而已。 VS Code各種屌炸天的功能,將來必定是強大的前端IDE。 通過下列5步讓VS ...
  • 前些日子,Insus.NET有實現《ASP.NET MVC使用jQuery實現Autocomplete》http://www.cnblogs.com/insus/p/5638895.html 。 但今天嘗試把此功能移到ASP.NET Ajax UpdatePanel環境中使用。網頁在第一次載入時是沒 ...
  • Networkcomms 是一款C# 語言編寫的TCP/UDP通信框架 作者是英國人 以前是收費的 目前作者已經開源 開源地址是:https://github.com/MarcFletcher/NetworkComms.Net networkcomms通訊框架使用簡單方便,性能穩定. 從github ...
  • 傻了吧唧的裝雙系統.成功的乾崩了原本的系統.現在重裝VS.閑的沒事胡扯幾句. WindowsAPI在每一臺Windows系統上開放標準API供開發人員調用.功能齊全.在這裡只介紹三個部分. 1.利用API控制滑鼠鍵盤. 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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...