一、 一对多 ------ 单向
在对象模型中,一对多的关联关系,使用集合来表示。
实例场景:班级对学生;Classes(班级)和Student(学生)之间是一对多的关系。
(一) 多对一、一对多的区别:
多对一关联映射:在多的一端加入一个外键指向一的一端,它维护的关系是多指向一的。
一对多关联映射:在多的一端加入一个外键指向一的一端,它维护的关系是一指向多的。
两者使用的策略是一样的,只是各自所站的角度不同。
(二) 实体类
Classes实体类:
public class Classes {
private int id;
private String name;
//一对多通常使用Set来映射,Set是不可重复内容。
//注意使用Set这个接口,不要使用HashSet,因为hibernate有延迟加载,
private Set<Student> students = new HashSet<Student>();
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;}
}
Student实体类:
public class Student {
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;}
}
(三) xml方式:映射
1、 Student映射文件:
<hibernate-mapping>
<class name="csy.model.Student">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="name" column="name"/>
</class>
</hibernate-mapping>
2、 Classes映射文件:
<hibernate-mapping>
<class name="csy.model.Classes">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="name" column="name"/>
<!--<set>标签 映射一对多(映射set集合),name="属性集合名称",然后在用<key>标签,在多的一端加入一个外键(column属性指定列名称)指向一的一端,再采用<one-to-many>标签说明一对多,还指定<set>标签中name="students"这个集合中的类型要使用完整的类路径(例如:class="csy.model.Student") -->
<set name="students">
<key column="classesid"/>
<one-to-many class="csy.model.Student"/>
</set>
</class>
</hibernate-mapping>
(四) annotation注解
一对多 多的一端只需要正常注解就可以了,需要在一的一端进行注解一对多的关系。
使用@OneToMany
@Entity
public class Classes {
private int id;
private String name;
// 一对多通常使用Set来映射,Set是不可重复内容。
// 注意使用Set这个接口,不要使用HashSet,因为hibernate有延迟加载,
private Set<Student> students = new HashSet<Student>();
@OneToMany//进行注解为一对多的关系
@JoinColumn(name="classesId")//在多的一端注解一个字段(名为classessid)
public Set<Student> getStudents() {
return students;
}
二、 一对多,多对一 -------双向
是加载学生时,能够把班级加载上来。当然加载班级也可以把学生加载上来
1、 在学生对象模型中,要持有班级的引用,并修改学生映射文件就可以了。。
2、 存储没有变化
3、 关系模型也没有变化
(一) xml方式:映射
学生映射文件修改后的
<class name="csy.model.Student">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="name" column="name"/>
<!--使用多对一标签映射 一对多双向,下列的column值必需与多的一端的key字段值一样。-->
<many-to-one name="classes" column="classesid"/>
</class>
如果在一对多的映射关系中采用一的一端来维护关系的话会存在以下两个缺点:①如果多的一端那个外键设置为非空时,则多的一端就存不进数据;②会发出多于的Update语句,这样会影响效率。所以常用对于一对多的映射关系我们在多的一端维护关系,并让多的一端维护关系失效(见下面属性)。
代码:
<class name="csy.model.Classes"">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="name" column="name"/>
<!--
<set>标签 映射一对多(映射set集合),name="属性集合名称"
然后在用<key>标签,在多的一端加入一个外键(column属性指定列名称)指向一的一端
再采用<one-to-many>标签说明一对多,还指定<set>标签中name="students"这个集合中的类型
要使用完整的类路径(例如:class="csy.model.Student")
inverse="false":一的一端维护关系失效(反转) :false:可以从一的一端维护关系(默认);true:从一的一端维护关系失效,这样如果在一的一端维护关系则不会发出Update语句。 -->
<set name="students" inverse="true">
<key column="classesid"/>
<one-to-many class="csy.model.Student"/>
</set>
</class>
(二) annotation方式注解
首先需要在多的一端持有一的一端的引用
因为一对多的双向关联,就是多对一的关系,我们一般在多的一端来维护关系,这样我们需要在多的一端实体类进行映射多对一,并且设置一个字段,而在一的一端只需要进行映射一对多的关系就可以了,如下:
多的一端
@Entity
public class Student {
private int id;
private String name;
private Classes classes;
@ManyToOne
@JoinColumn(name="classesId")
public Classes getClasses() {
return classes;
}
一的一端
@Entity
public class Classes {
private int id;
private String name;
// 一对多通常使用Set来映射,Set是不可重复内容。
// 注意使用Set这个接口,不要使用HashSet,因为hibernate有延迟加载,
private Set<Student> students = new HashSet<Student>();
@OneToMany(mappedBy="classes")//进行注解为一对多的关系
public Set<Student> getStudents() {
return students;}
mappedBy防止字段冗余。
(三) 关于inverse属性:
inverse主要用在一对多和多对多双向关联上,inverse可以被设置到集合标签<set>上,默认inverse为false,所以我们可以从一的一端和多的一端维护关联关系,如果设置inverse为true,则我们只能从多的一端维护关联关系。
注意:inverse属性,只影响数据的存储,也就是持久化
(四) Inverse和cascade区别:
Inverse是关联关系的控制方向
Casecade操作上的连锁反应