hibernate(三) 一對多對映關係

一杯涼茶發表於2016-11-29

    序言

       前面兩節講了hibernate的兩個配置檔案和hello world!。還有hibernate的一級快取和三種狀態,基本上hibernate就懂一點了,從這章起開始一個很重要的知識點,hibernate的關係對映。一對一、一對多、多對多的講解。,希望你們能從中學到東西,我也從中鞏固自己的知識

        計劃:

           one to many:單向一對多、many-to-one:單向多對一、雙向一對多 這一篇文章講完

           many-to-many:下一篇

           one-to-one:在下一篇

           最後一篇:cascade和inverse的講解。

                                            ---WH

 

一、瞭解什麼是一對多?

     一對多這種關係用的很多,但是很多人對此模糊不清,一對多不也就是多對一嗎,多對多中特殊的一個不也就是一對多嗎,為什麼還分的那麼清楚?並且還是什麼單向和雙向的那麼麻煩,其實原因很簡單,就是針對不同的情況和業務需求而產生的這種說法,

     例如:學生和班級

        單向一對多:一個班級對應多個學生。 也就是說,在某種業務情況下,我只需要知道從一個班級中知道有哪些學生,但是我不需要知道一個學生在哪個班級,這時候我就沒必要寫通過學生能查詢到對應班級這個業務

        單向多對一:多個學生對應一個班級,可以通過每個學生查詢到所在的班級名稱,而不能從班級中查詢到有哪些學生在裡面,這就是從多到一的單面考慮,也就是說,當我們的業務需求只需要通過學生能找到對應班級,而不需要通過班級知道有哪些學生的時候,就可以寫這樣的單向多對一的關係對映

        雙向一對多/雙向多對一:這兩個是一個意思,既然度雙向了,說明不管從哪一方去找另一方,度可以找得到,也就無所謂一對多,還是多對一了。從這個學生和班級來講,通過學生能知道他所在的班級,通過班級,能知道該班級下所有的學生。

      通過這個例子就知道了單向和雙向是幹嘛用的,就是根據不同的業務所規定的,如果你需要雙向就寫雙向的對映關係,如果只需要從一方到另一方,那麼就寫自己所需要的,單向一對多或者單向多對一。

     

    所以我們接下要講解的就是這三種,單向一對多、單向多對一、雙向一對多。

 

二、單向多對一

      多個使用者屬於同一個組,多個學生屬於同一個班級,多個學生屬於同一個宿舍,等等,很多關係是這種多對一。因為上面是拿班級和學生來舉測例子,那麼所有的例子我度會用這個。為了方便和你們閱讀。  

      多個學生屬於同一個班級。單向多對一    

                  User和Classes類的關係圖。

               

            資料庫中存在外來鍵值關係

            

    通過上面的圖可以看到,單向多對一就是在多的一方中加入外來鍵,通過該外來鍵就能夠找到對應的班級,因為不需要從一端的這方去管理這種關係,所以我們如果從班級這方來看,是不知道該班級下有哪些學生的。只能從多的一方也就是學生這邊找到是哪個班級。

    那麼xxx.hbm.xml如何編寫呢?

    User 需要有相應的能力,所以需要配置外來鍵關係。many to one

<class name="domain.User" table="user">
        <id name="id" column="id">
            <!-- 主鍵生成策略 -->
            <generator class="native"></generator>
        </id>
        <!-- 一些常規屬性 -->
        <property name="username"></property>
        <property name="sex"></property>
        <property name="age"></property>
        
        <!-- 重點在這裡 
            name:User類也就是本類中存放一方(Classes)物件的引用名稱。
            column:資料庫表中的外來鍵名稱。注意,是被外來鍵約束的欄位的名稱,寫這些配置檔案,要時刻記得那兩張資料庫表的關係。
         -->
        <many-to-one name="classes" column="cid"></many-to-one>
    
    </class>

    

    classes 班級 不需要有那種關係,只需要配置自己的屬性就行了

    <class name="domain.Classes" table="Classes">
        <id name="cid" column="cid">
            <generator class="native"></generator>
        </id>
        <property name="className"></property>
    </class>

  

    單向多對一的關係對映就是這樣簡單,原理就是在資料庫中多方設定外來鍵指向一方。 然後通過對映檔案來利用這個外來鍵幫我們達到我們的目的,這裡就是通過外來鍵,找到對應的班級放入我們自己類中的classes屬性中。

      many-to-one的屬性

        name:影射類屬性的名稱

        class:非必須的,不寫,hibernate會自己根據name的值去查詢

        column:關聯的欄位,也是非必須的,hibernate也會幫我們在查詢,但是不寫的話,User中的外來鍵名稱必須和Classes中的主鍵名稱相同。也就是關聯的欄位名稱要相同,這樣才找得到

        net-null:預設是false,就是不能為空

        lazy和fetch:後面的文章會講解到。

      

      

三、單向一對多

      說了單向多對一,現在來說說單向一對多,根據前面我們講的,其實就是換了一個角度去想這個問題,學生和班級,現在站在班級這方去看,肯定是需要通過班級能知曉所有在這個班學習的同學的資訊。    

              

        資料庫中還是沒變,不管是單向一對多還是單向多對一,永遠都市通過外來鍵來維護關係的,單向多對一:通過對映檔案知道,User的外來鍵能夠查詢到對應的班級。單向一對多:又是怎麼來實現通過User的外來鍵找到屬於本班的所有學生的呢?這就要看xx.hbm.xml對映檔案如何寫了。看下去你就會知道。

            

    User 不需要多方來維護關係(維護關係的意思就是不需要通過多方找到一方的資訊。)所以就不在需要many-to-one了

<class name="domain.User" table="user">
        <id name="id" column="id">
            <!-- 主鍵生成策略 -->
            <generator class="native"></generator>
        </id>
        <!-- 一些常規屬性 -->
        <property name="username"></property>
        <property name="sex"></property>
        <property name="age"></property>
        
    </class>

 

    Classes 由於是一方來維護關係,所以需要配置相關的關係。具體看下面的程式碼中的配置。

        <class name="domain.Classes" table="Classes">
        <id name="cid" column="cid">
            <generator class="native"></generator>
        </id>
        <property name="className"></property>

        <!--關鍵在這裡,
            name:set集合屬性的名稱
            key/column:這個是外來鍵名,這個外來鍵欄位名不一定要和本類的主鍵欄位名相同,這點要搞清楚,記住資料庫表的關係,誰指向誰就不會混淆
            one to many/class:一對多,所對映的類名(全限定類名,直接寫類名也可以,hibernate會幫我們自動寫好)
        -->
        <set name="set">
            <key column="cid"></key>
            <one-to-many class="User" />
        </set>
        
    </class>        

 

 這樣,單向一對多也是這樣配置好了,單向一對多是如何找到多的資訊的呢?通過對映檔案可以知道,通過本類中的主鍵值去尋找對映類中的外來鍵值,有匹配的就將其物件放置到set集合中來。所以說,不管是單向一對多還是單向多對一,都需要在多方加上外來鍵,也就是說,他們的原理度是一樣的,只是站的角度不一樣,單向一對多站的角度在於一方,一方如何通過外來鍵來達到自己的目的,就看自己的對映檔案如何編寫,單向多對一站的角度在多方,多方如何通過外來鍵來達到自己的目的,也要看自己的對映檔案的編寫。

 

 

四、雙向一對多/雙向多對一

      不管哪種叫法都市一樣的,別搞混淆了。

      既然知道了單向一對多,和單向多對一,這個也就很簡單了,就是通過雙方度能夠找到對方的資訊。

                  

 

         資料庫關係:還是跟上面兩種是一樣的。

        

User.hbm.xml

<class name="domain.User" table="user">
        <id name="id" column="id">
            <!-- 主鍵生成策略 -->
            <generator class="native"></generator>
        </id>
        <!-- 一些常規屬性 -->
        <property name="username"></property>
        <property name="sex"></property>
        <property name="age"></property>
        
        <!-- 重點在這裡 
            name:存放一方(Classes班級)的引用。
            column:資料庫表中的外來鍵名稱
         -->
        <many-to-one name="classes" column="cid"></many-to-one>
    
    </class>

 

Classes.hbm.xml

        <class name="domain.Classes" table="Classes">
        <id name="cid" column="cid">
            <generator class="native"></generator>
        </id>
        <property name="className"></property>

        <!--關鍵在這裡,
            name:set集合屬性的名稱
            key/column:這個是外來鍵名,這個外來鍵名不一定要和本類的主鍵欄位名相同,這點要搞清楚,
            one to many/class:一對多,所對映的類名(全限定類名,直接寫類名也可以,hibernate會幫我們自動寫好)
        -->
        <set name="set">
            <key column="cid"></key>
            <one-to-many class="User" />
        </set>
        
    </class>        

 

 

五、總結

    這樣就做好了雙向一對多的所有工作,很簡單把,明白了單向一對多和單向多對一,雙向的就超級簡單,就是你中有我,我中有你,大家的原理度是一樣,通過多方指向一方的外來鍵,只是站的角度不一樣,那麼所需要做的對映檔案的配置也就不一樣。注意一點:資料庫中的表欄位是沒有變化的,就是多方的外來鍵指向一方的主鍵,但是在實體類中的屬性會有變化,比如單向多對一中,在User中增加了一個Classes classes的變數,目的就是為了存放班級物件例項。在單向一對多中,在一方也就是Classes類中加了一個set集合用來裝自己的學生。這兩個屬性跟表欄位沒什麼關係,這個不要搞混淆

 

相關文章