上篇博客中介绍了Hibernate关联映射的一对一映射,今天来总结一对多总结。
【一对多】
1.举例
这种一对多的关系我们在关系模型中也是常见的。例如:班级和学生。
2.一对多单项关联映射
1)先从具体实例代码看起吧。O(∩_∩)O
①Student.java
package com.bjpowernode.hibernate;
public class Student {
private int id;
private String name;
// get和set略
}
②Student.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.bjpowernode.hibernate.Student" table="t_student">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
</class>
</hibernate-mapping>
③Classes.java类
package com.bjpowernode.hibernate;
import java.util.Set;
public class Classes {
private int id;
private String name;
// set中存放的是不可重复的,list中可重复,所以选择set
// Hibernate对set支持延迟加载
private Set students;
// get和set略
}
④Classes.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.bjpowernode.hibernate.Classes" table="t_classes">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<set name="students">
<key column="classesid"/>
<one-to-many class="com.bjpowernode.hibernate.Student"/>
</set>
</class>
</hibernate-mapping>
2)一对多单项关联映射原理:
一对多关联映射和多对一关联映射映射原理是一致的,都是在多的一端加入一个外键,指向一的一端
它们的区别在于维护的关系不同:
- 多对一维护的关系是:多指向一的关系,有了此关系,在加载多的时候可以将一加载上来
- 一对多维护的关系是:一指向多的关系,有了此关系,在加载一的时候可以将多加载上来
3)在一端维护关系存在缺陷:
因为多的一端Student不知道Classes的存在(也就是Student没有维护与Classes的关系),所以在保存Student的时候关系字段classesid是为null的,如果将该关系字段设置为非空,则将无法保存数据。另外因为Student不维护关系,而Classes维护关系,Classes就会发出多余的update语句,保证Classes和Student有关系,这样加载Classes的时候才可以把该Classes对应的学生加载上来
3.一对多双向关联映射
采用一对多双向关联映射的目的主要是为了主要是为了解决一对多单向关联的缺陷
1)一对多双向关联的映射方式:
在一的一端的集合上采用<key>标签,在多的一端加入一个外键,在多的一端采用<many-to-one>标签
注意:<key>标签和<many-to-one>标签加入的字段保持一直,否则会产生数据混乱。
2)实现代码如下:
①Student.java
package com.bjpowernode.hibernate;
public class Student {
private int id;
private String name;
private Classes classes;
// get和set略
}
②Student.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.bjpowernode.hibernate.Student" table="t_student">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<many-to-one name="classes" column="classesid"/>
</class>
</hibernate-mapping>
3)改善
还是那个问题,在多对一关联映射时我们也提到过,因为是双向映射,两方同时操作可能会出错,所以我们需要做一下控制。在多对一时我们用的是cascade属性,这里使用inverse属性。inverse属性可以用在一对多和多对多双向关联上,inverse属性默认为false,为false表示本端可以维护关系,如果inverse为true,则本端不能维护关系,会交给另一端维护关系,本端失效。所以一对多关联映射我们通常在多的一端维护关系,让一的一端失效,所以设置为inverse为true,在Classes.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.bjpowernode.hibernate.Classes" table="t_classes">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<set name="students" inverse="true">
<key column="classesid"/>
<one-to-many class="com.bjpowernode.hibernate.Student"/>
</set>
</class>
</hibernate-mapping>
4)inverse和cascade属性
- inverse是控制方向上的反转,只影响存储
- cascade是操作上的连锁反映