Hibernate映射详解(二)--多对一,一对多单向,一对多双向关联映射
??????? 首先來看一下多對一。舉個例子來說用戶和組。一個組中有多個用戶,一個用戶只能屬于一組。用戶和組之間就是一個多對一的關(guān)系的。如下圖
?????? 這個關(guān)系我們要怎樣維護(hù)呢?我們想象一下,假如在一的一端維護(hù)關(guān)系,即在group一端加一個字段userId來標(biāo)識學(xué)生。那設(shè)計出來的表格存儲數(shù)據(jù)是這個樣子的。
??????????????????
???????? 不解釋,直接看在多的一端維護(hù)關(guān)系????
??????????
??????? 不用說,大家就知道在多的一端維護(hù)數(shù)據(jù)冗余要少的多。怎么來解釋這個問題呢?大家想一下是多的記少的容易記,還是少的記多的容易記呢?舉個例子員工和老板。你說是老板記員工比較容易還是員工記老板比較容易呢?很明顯記少的比較容易啊,能維護(hù)二者的關(guān)系也能減少工作量。hibernate當(dāng)然也是這么做的。看一下實體和配置文件。這里只顯示部分代碼。
| public class Group { ??? privateint id;?? ??? private Stringname; ??? ************* ??? 省略get,set方法 ??? ************* } 從這里我們可以看出,group并不知道user的存在。 ? | public class User {? ??? privateint id;? ??? private Stringname;??? ??? private Groupgroup; ??? ************* ??? 省略get,set方法 ??? ************* } user中包含group屬性,來維持關(guān)系。 |
對應(yīng)的關(guān)系映射文件
| Group.hbm.xml <hibernate-mapping> ??? <classname="com.bjpowernode.hibernate.Group"table="t_group"> ??????? <idname="id"> ??????????? <generatorclass="native"/> ??????? </id> ??????? <propertyname="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的關(guān)系。解釋一下cascade級聯(lián),意思是指定兩個對象之間的操作聯(lián)動關(guān)系,對一個對象執(zhí)行了操作(他是對象之間的連鎖操作,只影響添加,刪除和修改。)之后,對其指定的級聯(lián)對象也需要執(zhí)行相同的操作。可以取值為all,none,save-update,delete。all代表在所有的情況下都執(zhí)行級聯(lián)操作。none指在所有情況下都不執(zhí)行級聯(lián)操作。save-update指在保存和更新的時候執(zhí)行級聯(lián)操作。delete指在刪除的時候執(zhí)行級聯(lián)操作。 --> ???????<many-to-onename="group"column="groupid"cascade="save-update"/> ??? </class> </hibernate-mapping> |
?
??????? 一對多的實現(xiàn)就是這個樣子了,那一對多反過來不就是多對一嗎?他們有什么不同呢?一對多關(guān)聯(lián)映射和多對一關(guān)聯(lián)映射的原理確實是一致的,都是在多的一端加入外鍵,指向一的一端。但是他們也是有區(qū)別的。我們先看一下他的實現(xiàn)。我們?nèi)匀徊捎靡粚Χ嗟膶W(xué)生用戶舉例。
| public class Group { ??? privateint id;??? ??? private Stringname; ??? private Set users; ??? ************* ??? 省略get,set方法 ??? ************* } ? ? ? | public class User { ? ??? privateint id; ??? ??? private Stringname; ??? ??? ************* ??? 省略get,set方法 ??? ************* } |
看一下對應(yīng)的配置文件又是怎么實現(xiàn)的呢?
| 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> ? ? ? |
??????? 這里面并沒有體現(xiàn)出任何與一的一端有關(guān)聯(lián)的字段。一對多的關(guān)聯(lián)最后生成的表格與多對一是一樣的。但是他們到底有什么區(qū)別呢?多對一的維護(hù)關(guān)系是多指向一的關(guān)系,有了此關(guān)系,在加載多的時候可以將一加載上來。即我們查詢用戶的時候,組也被查詢出來了。而一對多的關(guān)系,是指在加載一的時候可以將多加載進(jìn)來。即查詢組的時候,用戶也被查出來了。他們適用于不同的需求。
??????? 剛開始我們說過,不管是一對多還是多對一,都是在多的一端維護(hù)關(guān)系。從程序的執(zhí)行狀況來解釋一下這樣做的原因。若在一的一端維護(hù)關(guān)系,多的一端User并不知道Group的存在。所以在保存User的時候,關(guān)系字段groupId是為null的。如果將該關(guān)系字段設(shè)置為非空,則將無法保存數(shù)據(jù)。另外因為User不維護(hù)關(guān)系,Group維護(hù)關(guān)系,則在對Group進(jìn)行操作時,Group就會發(fā)出多余的update語句,去維持Group與User的關(guān)系,這樣加載Group的時候才會把該Group對應(yīng)的學(xué)生加載進(jìn)來。可見一對多關(guān)聯(lián)映射是存在這很大的問題的。那怎么解決這些問題呢?看一下下面的一對多雙向關(guān)聯(lián)。
?
實體類實現(xiàn)
| public class Group {? ??? privateint id;??? ??? private Stringname; ??? private Set users; ??? ************* ??? 省略get,set方法 ??? ************* } | public class User {? ??? privateint id;??? ??? private Stringname;?? ??? 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屬性他可以用在一對多和多對多雙向關(guān)聯(lián)上,inverse默認(rèn)為false,false表示本端可以維護(hù)關(guān)系,如果inverse為true,則表示本端不能維護(hù)關(guān)系,會交給另一端維護(hù)關(guān)系,本端失效。此處我們讓多的一端維護(hù)關(guān)系,一的一端失效。所以,此處設(shè)置為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的值保持一致。 ? ? ? ? ? |
?
??????????????? 通過一對多雙向關(guān)聯(lián)映射,我們將關(guān)系交給多的一端維護(hù),而且從一的一端也能夠看到多的一端。這樣就很好的解決了一對多單向關(guān)聯(lián)的缺陷,優(yōu)化之后的它查詢數(shù)據(jù),不管是一的一端還是多的一端,只需要一個sql語句就搞定了。要知道他不是由于需求驅(qū)動而設(shè)計的。?
??????? 今天,說了多對一,一對多單向,一對多雙向。總之,就是一與多之間的關(guān)系。下篇博客將講述多對多關(guān)聯(lián)映射,一對一主鍵關(guān)聯(lián)映射,一對一唯一外鍵關(guān)聯(lián)映射。
總結(jié)
以上是生活随笔為你收集整理的Hibernate映射详解(二)--多对一,一对多单向,一对多双向关联映射的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Hibernate一对多单向关联和双向关
- 下一篇: 【Hibernate步步为营】--(一对