Hibernate映射详解(二)--多对一,一对多单向,一对多双向关联映射
??????? 首先來看一下多對一。舉個例子來說用戶和組。一個組中有多個用戶,一個用戶只能屬于一組。用戶和組之間就是一個多對一的關系的。如下圖
?????? 這個關系我們要怎樣維護呢?我們想象一下,假如在一的一端維護關系,即在group一端加一個字段userId來標識學生。那設計出來的表格存儲數據是這個樣子的。
??????????????????
???????? 不解釋,直接看在多的一端維護關系????
??????????
??????? 不用說,大家就知道在多的一端維護數據冗余要少的多。怎么來解釋這個問題呢?大家想一下是多的記少的容易記,還是少的記多的容易記呢?舉個例子員工和老板。你說是老板記員工比較容易還是員工記老板比較容易呢?很明顯記少的比較容易啊,能維護二者的關系也能減少工作量。hibernate當然也是這么做的。看一下實體和配置文件。這里只顯示部分代碼。
| public class Group { ??? privateint id;?? ??? private Stringname; ??? ************* ??? 省略get,set方法 ??? ************* } 從這里我們可以看出,group并不知道user的存在。 ? | public class User {? ??? privateint id;? ??? private Stringname;??? ??? private Groupgroup; ??? ************* ??? 省略get,set方法 ??? ************* } user中包含group屬性,來維持關系。 |
對應的關系映射文件
| 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的關系。解釋一下cascade級聯,意思是指定兩個對象之間的操作聯動關系,對一個對象執行了操作(他是對象之間的連鎖操作,只影響添加,刪除和修改。)之后,對其指定的級聯對象也需要執行相同的操作。可以取值為all,none,save-update,delete。all代表在所有的情況下都執行級聯操作。none指在所有情況下都不執行級聯操作。save-update指在保存和更新的時候執行級聯操作。delete指在刪除的時候執行級聯操作。 --> ???????<many-to-onename="group"column="groupid"cascade="save-update"/> ??? </class> </hibernate-mapping> |
?
??????? 一對多的實現就是這個樣子了,那一對多反過來不就是多對一嗎?他們有什么不同呢?一對多關聯映射和多對一關聯映射的原理確實是一致的,都是在多的一端加入外鍵,指向一的一端。但是他們也是有區別的。我們先看一下他的實現。我們仍然采用一對多的學生用戶舉例。
| public class Group { ??? privateint id;??? ??? private Stringname; ??? private Set users; ??? ************* ??? 省略get,set方法 ??? ************* } ? ? ? | public class User { ? ??? privateint 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 {? ??? 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屬性他可以用在一對多和多對多雙向關聯上,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的值保持一致。 ? ? ? ? ? |
?
??????????????? 通過一對多雙向關聯映射,我們將關系交給多的一端維護,而且從一的一端也能夠看到多的一端。這樣就很好的解決了一對多單向關聯的缺陷,優化之后的它查詢數據,不管是一的一端還是多的一端,只需要一個sql語句就搞定了。要知道他不是由于需求驅動而設計的。?
??????? 今天,說了多對一,一對多單向,一對多雙向。總之,就是一與多之間的關系。下篇博客將講述多對多關聯映射,一對一主鍵關聯映射,一對一唯一外鍵關聯映射。
總結
以上是生活随笔為你收集整理的Hibernate映射详解(二)--多对一,一对多单向,一对多双向关联映射的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Hibernate一对多单向关联和双向关
- 下一篇: 【Hibernate步步为营】--(一对