1. 程式人生 > >hibernate的多對一,一對多單向關聯,雙向關聯區別與聯絡

hibernate的多對一,一對多單向關聯,雙向關聯區別與聯絡

首先來看一下多對一。舉個例子來說使用者和組。一個組中有多個使用者,一個使用者只能屬於一組。使用者和組之間就是一個多對一的關係的。如下圖

       這個關係我們要怎樣維護呢?我們想象一下,假如在一的一端維護關係,即在group一端加一個欄位userId來標識學生。那設計出來的表格儲存資料是這個樣子的。

                  

         不解釋,直接看在多的一端維護關係    

          

        不用說,大家就知道在多的一端維護資料冗餘要少的多。怎麼來解釋這個問題呢?大家想一下是多的記少的容易記,還是少的記多的容易記呢?舉個例子員工和老闆。你說是老闆記員工比較容易還是員工記老闆比較容易呢?很明顯記少的比較容易啊,能維護二者的關係也能減少工作量。hibernate

當然也是這麼做的。看一下實體和配置檔案。這裡只顯示部分程式碼。

public class Group {

    private int id;  

    private String name;

    *************

    省略get,set方法

    *************

}

從這裡我們可以看出,group並不知道user的存在

public class User { 

    private int id

    private String name;   

   private Group group;

    *************

    省略get,set方法

    *************

}

user中包含group屬性,來維持關係。

對應的關係對映檔案

Group.hbm.xml

<hibernate-mapping>

   <classname="com.bjpowernode.hibernate.Group"table="t_group">

        <idname="id">

            <generatorclass="native"/>

        </id>

        <property

name="name"/>

    </class>

</hibernate-mapping>

User.hbm.xml

<hibernate-mapping>

   <classname="com.bjpowernode.hibernate.User"table="t_user">

        <idname="id">

            <generatorclass="native"/>

        </id>

        <propertyname="name"/>

<!—這裡用來維繫與group的關係。解釋一下cascade級聯,意思是指定兩個物件之間的操作聯動關係,對一個物件執行了操作(他是物件之間的連鎖操作,隻影響新增,刪除和修改。)之後,對其指定的級聯物件也需要執行相同的操作。可以取值為allnonesave-updatedeleteall代表在所有的情況下都執行級聯操作。none指在所有情況下都不執行級聯操作。save-update指在儲存和更新的時候執行級聯操作。delete指在刪除的時候執行級聯操作。 -->

       <many-to-onename="group"column="groupid"cascade="save-update"/>

    </class>

</hibernate-mapping>

        一對多的實現就是這個樣子了,那一對多反過來不就是多對一嗎?他們有什麼不同呢?一對多關聯對映和多對一關聯對映的原理確實是一致的,都是在多的一端加入外來鍵,指向一的一端。但是他們也是有區別的。我們先看一下他的實現。我們仍然採用一對多的學生使用者舉例。

public class Group {

    private int id;   

    private Stringname;

   private Set users;

    *************

    省略get,set方法

    *************

}

public class User {

    private int id;

    private Stringname;

    *************

    省略get,set方法

    *************

}

看一下對應的配置檔案又是怎麼實現的呢?

Group.hbm.xml

<hibernate-mapping>

   <classname="com.bjpowernode.hibernate.Group"table="t_group">

        <idname="id">

            <generatorclass="native"/>

        </id>

        <propertyname="name"/>

<set name=”users”>

<key column=”groupId”/>

<one-to-many class="com.bjpowernode.hibernate.User">

</set>

    </class>

</hibernate-mapping>

User.hbm.xml

<hibernate-mapping>

   <classname="com.bjpowernode.hibernate.User"table="t_user">

        <idname="id">

            <generatorclass="native"/>

        </id>

        <propertyname="name"/>

    </class>

</hibernate-mapping>

        這裡面並沒有體現出任何與一的一端有關聯的欄位。一對多的關聯最後生成的表格與多對一是一樣的。但是他們到底有什麼區別呢?多對一的維護關係是多指向一的關係,有了此關係,在載入多的時候可以將一載入上來。即我們查詢使用者的時候,組也被查詢出來了。而一對多的關係,是指在載入一的時候可以將多載入進來。即查詢組的時候,使用者也被查出來了。他們適用於不同的需求。

        剛開始我們說過,不管是一對多還是多對一,都是在多的一端維護關係。從程式的執行狀況來解釋一下這樣做的原因。若在一的一端維護關係,多的一端User並不知道Group的存在。所以在儲存User的時候,關係欄位groupId是為null的。如果將該關係欄位設定為非空,則將無法儲存資料。另外因為User不維護關係,Group維護關係,則在對Group進行操作時,Group就會發出多餘的update語句,去維持Group與User的關係,這樣載入Group的時候才會把該Group對應的學生載入進來。可見一對多關聯對映是存在這很大的問題的。那怎麼解決這些問題呢?看一下下面的一對多雙向關聯。

實體類實現

public class Group { 

    private int id;   

    private String name;

   private Set users;

    *************

    省略get,set方法

    *************

}

public class User { 

    private int id;   

    private String name;  

    private Group group;

    *************

    省略get,set方法

    *************

}

接下來看一下對映檔案

group.hbm.xml

<hibernate-mapping>

   <classname="com.bjpowernode.hibernate.Group"table="t_group">

        <idname="id">

            <generatorclass="native"/>

        </id>

        <propertyname="name"/>

<!—inverse屬性他可以用在一對多和多對多雙向關聯上,inverse預設為falsefalse表示本端可以維護關係,如果inversetrue,則表示本端不能維護關係,會交給另一端維護關係,本端失效。此處我們讓多的一端維護關係,一的一端失效。所以,此處設定為true -->

<set name=”users” inverse=”true”>

<key column=”groupId”/>

<one-to-many class="com.bjpowernode.hibernate.User">

</set>

    </class>

</hibernate-mapping>

User.hbm.xml

<hibernate-mapping>

   <classname="com.bjpowernode.hibernate.User"table="t_user">

        <idname="id">

            <generatorclass="native"/>

        </id>

        <propertyname="name"/>

<many-to-one name=”groupId”/>

    </class>

</hibernate-mapping>

這裡要注意many-to-one的值要與key的值保持一致。

        通過一對多雙向關聯對映,我們將關係交給多的一端維護,而且從一的一端也能夠看到多的一端。