下面我们将介绍一下Hibernate中一对多的关联映射
一对多的关联映射其实和多对一的关联映射原理是一致的,都是在多的一端加入外键;
其两者的区别在于:
(1)多对一:多端维护一端的关系,在加载多端时,可以将一端加载上来。
(2)一对多:一端维护多端的关系,在加载一端时,可以将多端加载上来。
上一篇文章介绍了单向多对一的关联关系,下面来介绍一对多的关联关系,同样是使用上篇的两个实体类:用户(User)和分组(Group);在单向一对多的关系中,在Group类中加入了一个对User类的引用,如下所示:
package com.suo.bo;
import java.util.Set;
/**
* Group entity. @author MyEclipse Persistence Tools
*/
public class Group implements java.io.Serializable {
// Fields
private Integer id;
private String name;
//加入对User的引用(一对多,使用set)
private Set users;
// Property accessors
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public Set getUsers() {
return users;
}
public void setUsers(Set users) {
this.users = users;
}
}
Group.hbm.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!--
Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
<class name="com.suo.bo.Group" table="group" catalog="hibernate">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="increment" />
</id>
<property name="name" type="java.lang.String">
<column name="name" />
</property>
<!-- Group类中的users属性,表达本对象和User的一对多关系 -->
<set name="users">
<!-- key代表当前Group表的主键字段,column写入User表的内的外键字段groupId -->
<key column="groupId"></key>
<one-to-many class="com.suo.bo.User"></one-to-many>
</set>
</class>
</hibernate-mapping>
User.java
package com.suo.bo;
/**
* User entity. @author MyEclipse Persistence Tools
*/
public class User implements java.io.Serializable {
// Fields
private Integer id;
private String name;
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
User.hbm.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!--
Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
<class name="com.suo.bo.User" table="user" catalog="hibernate">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="increment" />
</id>
<property name="name" type="java.lang.String">
<column name="name" />
</property>
</class>
</hibernate-mapping>
1)因为多端User不知道Group的存在(也就是User不维护与Group的关系),所以在保存User时,关系字段groupId为null,如果该字段设置为非空,则将无法保存数据。
2)因为User不维护关系,而Group维护关系,Group就会发出多余的update语句,保证Group和User有关系,这样加载Group时才把该Users对应的用户加载上来。
为解决上述单向一对多出现的问题,一对多双向关联,在User类中加入了对Group的引用;
User类修改成如下;
package com.suo.bo;
/**
* User entity. @author MyEclipse Persistence Tools
*/
public class User implements java.io.Serializable {
// Fields
private Integer id;
private String name;
private Group group;//加入对Group的引用
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public Group getGroup() {
return group;
}
public void setGroup(Group group) {
this.group = group;
}
}
Group.java对于上面没什么变化package com.suo.bo;
import java.util.Set;
/**
* Group entity. @author MyEclipse Persistence Tools
*/
public class Group implements java.io.Serializable {
// Fields
private Integer id;
private String name;
//加入对User的引用(一对多,使用set)
private Set users;
// Property accessors
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public Set getUsers() {
return users;
}
public void setUsers(Set users) {
this.users = users;
}
}
Group.hbm.xml映射文件发生了变化:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!--
Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
<class name="com.suo.bo.Group" table="group" catalog="hibernate">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="increment" />
</id>
<property name="name" type="java.lang.String">
<column name="name" />
</property>
<!-- Group类中的users属性,表达本对象和User的一对多关系 -->
<!-- inverse控制反转,设置为true时,让多的一端维护关系,使一的一端失效 -->
<set name="users" inverse="true">
<!-- key代表当前Group表的主键字段 -->
<key column="groupId"></key>
<one-to-many class="com.suo.bo.User"></one-to-many>
</set>
</class>
</hibernate-mapping>
<!-- inverse属性:
inverse属性可以用在一对多和多对多双向关联上,inverse属性默认为false,为false表示本端维护关系,
如果inverse为true,则本端不能维护关系,会交给另一端维护关系,本端失效。
所以一对多关联映射我们通常在多的一端维护关系,让一的一端失效,所以设置为inverse为true。注意:inverse属性,只影响数据的存储,也就是持久化。 -->
User.hbm.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!--
Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
<class name="com.suo.bo.User" table="user" catalog="hibernate">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="increment" />
</id>
<!-- group属性 ,表达该对象与Group是多对一的关系 此处column一定与group.hbm.xml中key column="groupId"保持一致-->
<many-to-one name="group" class="com.suo.Group" column="groupId"></many-to-one>
<property name="name" type="java.lang.String">
<column name="name" /> </property>
</class>
</hibernate-mapping>