上上篇博文【SSH進階之路】Hibernate映射——一對一單向關聯映射(五),我們介紹了一對一的單向關聯映射,單向是指只能從人(Person)這端加載身份證端(IdCard),但是反過來,不能從身份證端加載人得信息。
上篇博文【SSH進階之路】Hibernate映射——一對一雙向關聯映射(六),雙向關聯映射解決了單向關聯映射只能從一端加載信息的缺陷,當然,雙向關聯映射並不影響存儲,只影響加載。下面我們開始今天的內容:
一對多關聯映射
映射原理
一對多關聯映射和多對一關聯映射的映射原理是一致的,都是在多的一端加入一個外鍵,指向一的一端。關聯關系都是由多端維護,只是在寫映射時發生了變化。
多對一和一對多的區別
多對一和一對多的區別在於維護的關系不同:
(1)多對一:多端維護一端的關系,在加載多端時,可以將一端加載上來。
(2)一對多:一端維護多端的關系,在加載一端時,可以將多端加載上來。
分類
一對多單向關聯映射
對象模型

從對象模型中,我們可以看出,Group持有User的一個引用。由於是單向關聯,所以數據在加載Group時,會把User加載上來,但是User並不知道Group的存在。
我們先看一下Group和User的實體,以及映射文件。
Group
- package com.liang.hibernate;
- import java.util.Set;
- public class Group {
- private int id;
- private String name;
- private Set users;
- public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public Set getUsers() {
- return users;
- }
- public void setUsers(Set users) {
- this.users = users;
- }
- }
User
- package com.liang.hibernate;
- public class User {
- private int id;
- private String name;
- public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- }
User.hbm.xml
- <?xml version="1.0"?>
- <!DOCTYPE hibernate-mapping PUBLIC
- "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
- <hibernate-mapping>
- <class name="com.liang.hibernate.User" table="t_user">
- <id name="id">
- <generator class="native"/>
- </id>
- <property name="name"/>
- </class>
- </hibernate-mapping>
Group.hbm.xml
- <?xml version="1.0"?>
- <!DOCTYPE hibernate-mapping PUBLIC
- "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
- <hibernate-mapping>
- <class name="com.liang.hibernate.Group" table="t_group">
- <id name="id">
- <generator class="native"/>
- </id>
- <property name="name"/>
- <!-- users屬性,表達的是本對象與User的一對多的關系 -->
- <set name="users">
- <!--當前表(Group)的主鍵-->
- <key column="groupid"/>
- <one-to-many class="com.liang.hibernate.User"/>
- </set>
- </class>
- </hibernate-mapping>
生成的表結構和測試數據

缺點
1)因為多端User不知道Group的存在(也就是User不維護與Group的關系),所以在保存User時,關系字段groupId為null,如果該字段設置為非空,則將無法保存數據。
2)因為User不維護關系,而Group維護關系,Group就會發出多余的update語句,保證Group和User有關系,這樣加載Group時才把該Users對應的用戶加載上來。
一對多雙向關聯映射
對象模型

雙向關聯映射對比單向關聯映射,對象的加載方向由單向變成了雙向。
我們看一下Group和User的實體,映射文件
Group
- package com.liang.hibernate;
- import java.util.Set;
- public class Group {
- private int id;
- private String name;
- private Set users;
- public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public Set getUsers() {
- return users;
- }
- public void setUsers(Set users) {
- this.users = users;
- }
- }
User
- package com.liang.hibernate;
- public class User {
- private int id;
- private String name;
- private Group groups;
- public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public Group getGroups() {
- return groups;
- }
- public void setGroups(Group groups) {
- this.groups = groups;
- }
- }
Group.hbm.xml
- <?xml version="1.0"?>
- <!DOCTYPE hibernate-mapping PUBLIC
- "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
- <hibernate-mapping package="com.liang.hibernate">
- <class name="Group" table="t_group">
- <id name="id">
- <generator class="native"/>
- </id>
- <property name="name"/>
- <!-- 影響控制反轉:inverse="false",多的一端維護關系,讓一的一端失效 -->
- <set name="users" inverse="true">
- <key column="groupid" not-null="true"/>
- <one-to-many class="User"/>
- </set>
- </class>
- </hibernate-mapping>
User.hbm.xml
- <?xml version="1.0"?>
- <!DOCTYPE hibernate-mapping PUBLIC
- "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
- <hibernate-mapping package="com.liang.hibernate">
- <class name="User" table="t_user">
- <id name="id">
- <generator class="native"/>
- </id>
- <property name="name"/>
- <!-- groups屬性,表達的是本對象與Group的多對一的關系 -->
- <many-to-one name="groups" class="Group" column="groupid"/>
- </class>
- </hibernate-mapping>
生成的表和測試數據


一對多雙向關聯的映射方式:
1)在一的一端的集合上采用<key>標簽,在多的一端加入一個外鍵
2)在多的一端采用<many-to-one>標簽
注意:<key>標簽和<many-to-one>標簽加入的字段保持一直,否則會產生數據混亂。
inverse屬性:
inverse屬性可以用在一對多和多對多雙向關聯上,inverse屬性默認為false,為false表示本端維護關系,如果inverse為true,則本端不能維護關系,會交給另一端維護關系,本端失效。所以一對多關聯映射我們通常在多的一端維護關系,讓一的一端失效,所以設置為inverse為true。
注意:inverse屬性,只影響數據的存儲,也就是持久化。
目的
一對多雙向關聯映射的目的主要是為了解決一對多單向關聯的缺陷而不是需求驅動的。
總結
一對多關聯映射還是很簡單的,下篇博文我們介紹多對多關聯映射。謝謝關注。

