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

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

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

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

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

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

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

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

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

注意:需要在Person.hbm.xml映射文件中配置one-to-one標簽戏售,如下:

<?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會取得關(guān)聯(lián)對象的標識 -->  
            <generator class="foreign">  
                <!-- property只關(guān)聯(lián)對象 -->  
                <param name="property">idCard</param>  
            </generator>  
        </id>  
        <property name="name"/>  
        <!-- one-to-one指示hibernate如何加載其關(guān)聯(lián)對象,默認根據(jù)主鍵加載  
            也就是拿到關(guān)系字段值灌灾,根據(jù)對端的主鍵來加載關(guān)聯(lián)對象  
         -->  
        <one-to-one name="idCard" constrained="true"/>  
    </class>  
</hibernate-mapping>  
  • 唯一外鍵關(guān)聯(lián):外鍵關(guān)聯(lián)搓译,本來是用于多對一的配置,但是加上唯一的限制之后(采用<many-to-one>標簽來映射锋喜,指定多的一端unique為true些己,這樣就限制了多的一端的多重性為一),也可以用來表示一對一關(guān)聯(lián)關(guān)系嘿般,其實它就是多對一的特殊情況轴总。如下圖:

需要在Person.hbm.xml映射文件中配置many-to-one標簽,并指定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)對象 -->  
                <param name="property">idCard</param>  
            </generator>  
        </id>  
        <property name="name"/>  
        <many-to-one name="idCard" unique="true"/>  
    </class>  
</hibernate-mapping> 

注意:因為一對一的主鍵關(guān)聯(lián)映射擴展性不好,當我們的需要發(fā)生改變想要將其變?yōu)橐粚Χ嗟臅r候變無法操作了功偿,所以我們遇到一對一關(guān)聯(lián)的時候經(jīng)常會采用唯一外鍵關(guān)聯(lián)來解決問題盆佣,而很少使用一對一主鍵關(guān)聯(lián)往堡。

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

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

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

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

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

一對多關(guān)聯(lián)映射和多對一關(guān)聯(lián)映射原理是一致的虑灰,都是在多的一端加入一個外鍵,指向一的一端痹兜。如下圖(學生和班級):

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

  • 多對一維護的關(guān)系是:多指向一的關(guān)系穆咐,有了此關(guān)系,加載多的時候可以將一加載上來字旭。
  • 一對多維護的關(guān)系是:一指向多的關(guān)系对湃,有了此關(guān)系,在加載一的時候可以將多加載上來遗淳。

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

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

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

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

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

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

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

對比單向一對一映射,需要在IdCard也加入<one-to-one>標簽屈暗。示意圖如下:

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

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

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

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

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

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

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

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

  • 在一的一端的集合上采用<key>標簽养叛,在多的一端加入一個外鍵
  • 在多的一端采用<many-to-one>標簽

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

在Classes的一端加入如下標簽映射:

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

在Student的一端加入如下標簽映射:

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

了解inverse屬性:

  • inverse屬性可以用在一對多和多對多雙向關(guān)聯(lián)上弃甥,inverse屬性默認為false爽室,為false表示本端可以維護關(guān)系,如果inverse為true潘飘,則本端不能維護關(guān)系肮之,會交給另一端維護關(guān)系,本端失效卜录。所以一對多關(guān)聯(lián)映射我們通常在多的一端維護關(guān)系戈擒,讓一的一端失效。
  • inverse是控制方向上的反轉(zhuǎn)艰毒,只影響存儲筐高。

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

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

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

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é)

對于上面的七種關(guān)聯(lián)映射柑土,最重要的就是一對多的映射,因為它更貼近我們的現(xiàn)實生活绊汹,比如:教室和學生就可以是典型的一對多的關(guān)系稽屏,而我們開發(fā)軟件的目的之一就是為了解決一些生活中重復性問題,把那些重復的問題交給計算機來幫助我們完成西乖,從而提高我們的工作效率狐榔。


本文永久更新地址: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)容合作請聯(lián)系作者
  • 序言:七十年代末坛增,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子薄腻,更是在濱河造成了極大的恐慌收捣,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件庵楷,死亡現(xiàn)場離奇詭異罢艾,居然都是意外死亡,警方通過查閱死者的電腦和手機尽纽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進店門咐蚯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蜓斧,你說我怎么就攤上這事仓蛆。” “怎么了挎春?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵看疙,是天一觀的道長。 經(jīng)常有香客問我直奋,道長能庆,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任脚线,我火速辦了婚禮搁胆,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘邮绿。我一直安慰自己渠旁,他們只是感情好,可當我...
    茶點故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布船逮。 她就那樣靜靜地躺著顾腊,像睡著了一般。 火紅的嫁衣襯著肌膚如雪挖胃。 梳的紋絲不亂的頭發(fā)上杂靶,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天,我揣著相機與錄音酱鸭,去河邊找鬼吗垮。 笑死,一個胖子當著我的面吹牛凹髓,可吹牛的內(nèi)容都是我干的烁登。 我是一名探鬼主播,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼蔚舀,長吁一口氣:“原來是場噩夢啊……” “哼饵沧!你這毒婦竟也來了蚀之?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤捷泞,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后寿谴,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體锁右,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年讶泰,在試婚紗的時候發(fā)現(xiàn)自己被綠了咏瑟。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡痪署,死狀恐怖码泞,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情狼犯,我是刑警寧澤余寥,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站悯森,受9級特大地震影響宋舷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜瓢姻,卻給世界環(huán)境...
    茶點故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一祝蝠、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧幻碱,春花似錦绎狭、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽张峰。三九已至,卻和暖如春社付,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背邻耕。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工鸥咖, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人兄世。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓啼辣,卻偏偏與公主長得像,于是被迫代替她去往敵國和親御滩。 傳聞我的和親對象是個殘疾皇子鸥拧,可洞房花燭夜當晚...
    茶點故事閱讀 44,700評論 2 354

推薦閱讀更多精彩內(nèi)容