hibernate的多對一,一對多單向關聯,雙向關聯區別與聯絡
首先來看一下多對一。舉個例子來說使用者和組。一個組中有多個使用者,一個使用者只能屬於一組。使用者和組之間就是一個多對一的關係的。如下圖
這個關係我們要怎樣維護呢?我們想象一下,假如在一的一端維護關係,即在group一端加一個欄位userId來標識學生。那設計出來的表格儲存資料是這個樣子的。
不解釋,直接看在多的一端維護關係
不用說,大家就知道在多的一端維護資料冗餘要少的多。怎麼來解釋這個問題呢?大家想一下是多的記少的容易記,還是少的記多的容易記呢?舉個例子員工和老闆。你說是老闆記員工比較容易還是員工記老闆比較容易呢?很明顯記少的比較容易啊,能維護二者的關係也能減少工作量。hibernate
|
|
對應的關係對映檔案
Group.hbm.xml <hibernate-mapping> <classname="com.bjpowernode.hibernate.Group"table="t_group"> <idname="id"> <generatorclass="native"/> </id> <property </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級聯,意思是指定兩個物件之間的操作聯動關係,對一個物件執行了操作(他是物件之間的連鎖操作,隻影響新增,刪除和修改。)之後,對其指定的級聯物件也需要執行相同的操作。可以取值為all,none,save-update,delete。all代表在所有的情況下都執行級聯操作。none指在所有情況下都不執行級聯操作。save-update指在儲存和更新的時候執行級聯操作。delete指在刪除的時候執行級聯操作。 --> <many-to-onename="group"column="groupid"cascade="save-update"/> </class> </hibernate-mapping> |
一對多的實現就是這個樣子了,那一對多反過來不就是多對一嗎?他們有什麼不同呢?一對多關聯對映和多對一關聯對映的原理確實是一致的,都是在多的一端加入外來鍵,指向一的一端。但是他們也是有區別的。我們先看一下他的實現。我們仍然採用一對多的學生使用者舉例。
|
|
看一下對應的配置檔案又是怎麼實現的呢?
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對應的學生載入進來。可見一對多關聯對映是存在這很大的問題的。那怎麼解決這些問題呢?看一下下面的一對多雙向關聯。
實體類實現
|
|
接下來看一下對映檔案
group.hbm.xml <hibernate-mapping> <classname="com.bjpowernode.hibernate.Group"table="t_group"> <idname="id"> <generatorclass="native"/> </id> <propertyname="name"/> <!—inverse屬性他可以用在一對多和多對多雙向關聯上,inverse預設為false,false表示本端可以維護關係,如果inverse為true,則表示本端不能維護關係,會交給另一端維護關係,本端失效。此處我們讓多的一端維護關係,一的一端失效。所以,此處設定為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的值保持一致。 |
通過一對多雙向關聯對映,我們將關係交給多的一端維護,而且從一的一端也能夠看到多的一端。