Hibernate的關(guān)聯(lián)映射

首先我們了解一個(gè)名詞ORM,全稱是(Object Relational Mapping),即對(duì)象關(guān)系映射。ORM的實(shí)現(xiàn)思想就是將關(guān)系型數(shù)據(jù)庫中表的數(shù)據(jù)映射成對(duì)象,以對(duì)象的形式展現(xiàn),這樣開發(fā)人員就可以把對(duì)數(shù)據(jù)庫的操作轉(zhuǎn)化為對(duì)這些對(duì)象的操作。Hibernate正是實(shí)現(xiàn)了這種思想,達(dá)到了方便開發(fā)人員以面向?qū)ο蟮乃枷雭韺?shí)現(xiàn)對(duì)數(shù)據(jù)庫的操作。

Hibernate在實(shí)現(xiàn)ORM功能的時(shí)候主要用到的文件有:映射類(*.java)、映射文件(*.hbm.xml)和數(shù)據(jù)庫配置文件(*.properties/*.cfg.xml),它們各自的作用如下:

  • 映射類(*.java):它是描述數(shù)據(jù)庫表的結(jié)構(gòu),表中的字段在類中被描述成屬性,將來就可以實(shí)現(xiàn)把表中的記錄映射成為該類的對(duì)象了。
  • 映射文件(*.hbm.xml):它是指定數(shù)據(jù)庫表和映射類之間的關(guān)系,包括映射類和數(shù)據(jù)庫表的對(duì)應(yīng)關(guān)系、表字段和類屬性的對(duì)應(yīng)關(guān)系。
  • 數(shù)據(jù)庫配置文件(*.properties/*.cfg.xml):它是指定與數(shù)據(jù)庫連接時(shí)需要的連接信息,比如連接哪種數(shù)據(jù)庫、登錄數(shù)據(jù)庫的用戶名、密碼以及連接字符串等。當(dāng)然還可以把映射類的地址映射信息放在這里。

接下來讓我們一起走進(jìn)Hibernate的幾種關(guān)聯(lián)映射關(guān)系:

單向一對(duì)一關(guān)聯(lián)映射(one-to-one):

兩個(gè)對(duì)象之間一對(duì)的關(guān)系,例如:Person(人)- IdCard(身份證)

有兩種策略可以實(shí)現(xiàn)一對(duì)一的關(guān)聯(lián)映射:

  • 主鍵關(guān)聯(lián):即讓兩個(gè)對(duì)象具有相同的主鍵值,以表明它們之間的一一對(duì)應(yīng)的關(guān)系;數(shù)據(jù)庫表不會(huì)有額外的字段來維護(hù)它們之間的關(guān)系,僅通過表的主鍵來關(guān)聯(lián)。如下圖:

注意:需要在Person.hbm.xml映射文件中配置one-to-one標(biāo)簽,如下:

<?xml version="1.0"?>  
<!DOCTYPE hibernate-mapping PUBLIC   
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
<hibernate-mapping>  
    <class name="com.nnngu.Person" table="t_person">  
        <id name="id">  
            <!-- 采用foreign生成策略,foreign會(huì)取得關(guān)聯(lián)對(duì)象的標(biāo)識(shí) -->  
            <generator class="foreign">  
                <!-- property只關(guān)聯(lián)對(duì)象 -->  
                <param name="property">idCard</param>  
            </generator>  
        </id>  
        <property name="name"/>  
        <!-- one-to-one指示hibernate如何加載其關(guān)聯(lián)對(duì)象,默認(rèn)根據(jù)主鍵加載  
            也就是拿到關(guān)系字段值,根據(jù)對(duì)端的主鍵來加載關(guān)聯(lián)對(duì)象  
         -->  
        <one-to-one name="idCard" constrained="true"/>  
    </class>  
</hibernate-mapping>  
  • 唯一外鍵關(guān)聯(lián):外鍵關(guān)聯(lián),本來是用于多對(duì)一的配置,但是加上唯一的限制之后(采用<many-to-one>標(biāo)簽來映射,指定多的一端unique為true,這樣就限制了多的一端的多重性為一),也可以用來表示一對(duì)一關(guān)聯(lián)關(guān)系,其實(shí)它就是多對(duì)一的特殊情況。如下圖:

需要在Person.hbm.xml映射文件中配置many-to-one標(biāo)簽,并指定unique為true,如下:

<?xml version="1.0"?>  
<!DOCTYPE hibernate-mapping PUBLIC   
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
<hibernate-mapping>  
    <class name="com.nnngu.Person" table="t_person">  
        <id name="id">  
            <generator class="native">  
                <!-- property只關(guān)聯(lián)對(duì)象 -->  
                <param name="property">idCard</param>  
            </generator>  
        </id>  
        <property name="name"/>  
        <many-to-one name="idCard" unique="true"/>  
    </class>  
</hibernate-mapping> 

注意:因?yàn)橐粚?duì)一的主鍵關(guān)聯(lián)映射擴(kuò)展性不好,當(dāng)我們的需要發(fā)生改變想要將其變?yōu)橐粚?duì)多的時(shí)候變無法操作了,所以我們遇到一對(duì)一關(guān)聯(lián)的時(shí)候經(jīng)常會(huì)采用唯一外鍵關(guān)聯(lián)來解決問題,而很少使用一對(duì)一主鍵關(guān)聯(lián)。

單向多對(duì)一關(guān)聯(lián)映射(many-to-one):

多對(duì)一關(guān)聯(lián)映射原理:在多的一端加入一個(gè)外鍵,指向一的一端,如下圖:

關(guān)鍵映射代碼——在多的一端加入如下標(biāo)簽映射:

<many-to-one name="group" column="groupid"/>  

單向一對(duì)多關(guān)聯(lián)映射(one-to-many):

一對(duì)多關(guān)聯(lián)映射和多對(duì)一關(guān)聯(lián)映射原理是一致的,都是在多的一端加入一個(gè)外鍵,指向一的一端。如下圖(學(xué)生和班級(jí)):

注意:它與多對(duì)一的區(qū)別是維護(hù)的關(guān)系不同

  • 多對(duì)一維護(hù)的關(guān)系是:多指向一的關(guān)系,有了此關(guān)系,加載多的時(shí)候可以將一加載上來。
  • 一對(duì)多維護(hù)的關(guān)系是:一指向多的關(guān)系,有了此關(guān)系,在加載一的時(shí)候可以將多加載上來。

關(guān)鍵映射代碼——在一的一端加入如下標(biāo)簽映射:

<set name="students">  
      <key column="classesid"/>  
      <one-to-many class="com.nnngu.Student"/>  
</set> 

單向多對(duì)多映射(many-to-many):

多對(duì)多關(guān)聯(lián)映射需要新增加一張表才完成基本映射,如下圖:

關(guān)鍵映射代碼——可以在User的一端加入如下標(biāo)簽映射:

<set name="roles" table="t_user_role">  
     <key column="user_id"/>  
     <many-to-many class="com.nnngu.Role" column="role_id"/>  
</set>

雙向一對(duì)一關(guān)聯(lián)映射:

對(duì)比單向一對(duì)一映射,需要在IdCard也加入<one-to-one>標(biāo)簽。示意圖如下:

雙向一對(duì)一主鍵映射關(guān)鍵映射代碼——在IdCard端新加入如下標(biāo)簽映射:

<one-to-one name="person"/> 

雙向一對(duì)一唯一外鍵映射關(guān)鍵映射代碼——在IdCard端新加入如下標(biāo)簽映射:

<one-to-one name="person"property-ref="idCard"/>  

注意:一對(duì)一唯一外鍵關(guān)聯(lián)雙向采用<one-to-one>標(biāo)簽映射,必須指定<one-to-one>標(biāo)簽中的property-ref屬性為關(guān)系字段的名稱

雙向一對(duì)多關(guān)聯(lián)映射(非常重要):

采用雙向一對(duì)多關(guān)聯(lián)映射的目的主要是為了解決單向一對(duì)多關(guān)聯(lián)的缺陷。

雙向一對(duì)多關(guān)聯(lián)的映射方式:

  • 在一的一端的集合上采用<key>標(biāo)簽,在多的一端加入一個(gè)外鍵
  • 在多的一端采用<many-to-one>標(biāo)簽

注意:<key>標(biāo)簽和<many-to-one>標(biāo)簽加入的字段要保持一致,否則會(huì)產(chǎn)生數(shù)據(jù)混亂。

在Classes的一端加入如下標(biāo)簽映射:

<set name="students"inverse="true">  
      <key column="classesid"/>  
      <one-to-many class="com.nnngu.Student"/>  
</set> 

在Student的一端加入如下標(biāo)簽映射:

<many-to-one name="classes" column="classesid"/>  

了解inverse屬性:

  • inverse屬性可以用在一對(duì)多和多對(duì)多雙向關(guān)聯(lián)上,inverse屬性默認(rèn)為false,為false表示本端可以維護(hù)關(guān)系,如果inverse為true,則本端不能維護(hù)關(guān)系,會(huì)交給另一端維護(hù)關(guān)系,本端失效。所以一對(duì)多關(guān)聯(lián)映射我們通常在多的一端維護(hù)關(guān)系,讓一的一端失效。
  • inverse是控制方向上的反轉(zhuǎn),只影響存儲(chǔ)。

雙向多對(duì)多關(guān)聯(lián)映射:

雙向的目的就是為了兩端都能將對(duì)方加載上來,和單向多對(duì)多的區(qū)別就是雙向需要在兩端都加入標(biāo)簽映射,需要注意的是:

  • 生成的中間表名稱必須一樣
  • 生成的中間表中的字段必須一樣

Role(角色)端關(guān)鍵映射代碼:

<set name="users" table="t_user_role">  
       <key column="role_id"/>  
       <many-to-many class="com.nnngu.User" column="user_id"/>  
</set>  

User(用戶)端關(guān)鍵映射代碼:

<set name="roles" table="t_user_role">  
      <key column="user_id"/>  
      <many-to-many class="com. nnngu.Role" column="role_id"/>  
</set> 

總結(jié)

對(duì)于上面的七種關(guān)聯(lián)映射,最重要的就是一對(duì)多的映射,因?yàn)樗N近我們的現(xiàn)實(shí)生活,比如:教室和學(xué)生就可以是典型的一對(duì)多的關(guān)系,而我們開發(fā)軟件的目的之一就是為了解決一些生活中重復(fù)性問題,把那些重復(fù)的問題交給計(jì)算機(jī)來幫助我們完成,從而提高我們的工作效率。


本文永久更新地址:https://github.com/nnngu/LearningNotes/blob/master/_posts/2018-03-23-Hibernate%E7%9A%84%E5%85%B3%E8%81%94%E6%98%A0%E5%B0%84.md

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容