【Hibernate】关系映射
2017-03-09 18:06
113 查看
上一篇博客从整体上认识了一下Hibernate的映射关系,今天就来总结一些常用的关系映射。
一.多对一关联映射
比如用户和组的关系,多个用户可能对应一个组,所以我们就会在“多”的一端加入外键,指向“一”的一端。
![](https://img-blog.csdn.net/20170309163800544?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveWl3YW5neGlibG9n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
1.首先我们会在“多”端的实体中引入“一”端的实体,并生成相应的get,set方法
比如多个用户对应一个分组,我们就会在User实体类中引用Group
private Group group;
public Group getGroup() {
return group;
}
public void setGroup(Group group) {
this.group = group;
}
2.在“多”端的配置文件中添加关系映射,比如在user.hbm.xml中添加标签:
<hibernate-mapping>
<class name="com.bjpowernode.hibernate.User" table="t_user">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<!--维护多对一关系-->
<many-to-one name="group" column="groupid" cascade="save-update"/>
</class>
</hibernate-mapping>
二.单向的一对一关联映射
主键关联
就是让两个实体的主键一样,就不需要加入多余的字段了。比如一个学生对应一个身份证号,一个学生对应一条户口信息等等,都是一对一关联映射。
![](https://img-blog.csdn.net/20170309165739417?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveWl3YW5neGlibG9n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
1、Person实体里要持有IdCard的引用。在Person实体里加入属性:Private IdCard idCard;
2、Person端维护关系,所以需要重点看Person的配置文件,在Person.hbm.xml中,使Person中的Id既为主键又为外键。所以需要修改Person中的id标签:告诉Person里的id去关联哪个实体里的id。
<hibernate-mapping>
<class name="com.tgb.hibernate.Person" table="t_person">
<id name="id">
<!-- 采用foreign生成策略,forgeign会取得关联对象的标识 -->
<generator class="foreign">
<!-- property只关联对象 -->
<param name="property">idCard</param>
</generator>
</id>
<property name="name"/>
<!--
one-to-one指示hibernate如何加载其关联对象,默认根据主键加载
也就是拿到关系字段值,根据对端的主键来加载关联对象
constrained="true表示,当前主键(person的主键)还是一个外键
参照了对端的主键(IdCard的主键),也就是会生成外键约束语句
-->
<one-to-one name="idCard" constrained="true"/>
</class>
</hibernate-mapping>唯一外键关联
外键关联,本来是用于多对一的配置,但是加上唯一的限制之后(采用<many-to-one>标签来映射,指定多的一端unique为true,这样就限制了多的一端的多重性为一),也可以用来表示一对一关联关系,其实它就是多对一的特殊情况。
![](https://img-blog.csdn.net/20170309171602796?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveWl3YW5neGlibG9n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
1、Person.java是实体里有IdCard的引用,即加入属性:private IdCard idCard;IdCard.java里没有Person引用。
2、配置文件:IdCard.hbm.xml里都是普通属性。Person.hbm.xml的主键生成策略为native,使用<many-to-one>标签来维护外键,<many-to-one name="idCard" unique="true"/>。
注意:因为一对一的主键关联映射扩展性不好,当我们的需要发生改变想要将其变为一对多的时候变无法操作了,所以我们遇到一对一关联的时候经常会采用唯一外键关联来解决问题,而很少使用一对一主键关联。
三.双向的一对一关联映射
![](https://img-blog.csdn.net/20170309174514263?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveWl3YW5neGlibG9n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
1、在Person和IdCard里添加对应端的引用,即添加相应属性。
2、在person.hbm.xml中添加<many-to-one>标签
<many-to-one name="idCard" unique="true"/>
在IdCard端新加入如下标签映射:
[java] view
plain copy
<one-to-one name="person"property-ref="idCard"/>
注意:一对一唯一外键关联双向采用<one-to-one>标签映射,必须指定<one-to-one>标签中的property-ref属性为关系字段的名称
四.单向一对多关联映射
一对多关联映射和多对一关联映射的原理是一致的,都是在多的一端加入一个外键,指向一的一端。比如学生和班级的关系:
![](https://img-blog.csdn.net/20170309175535613?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveWl3YW5neGlibG9n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
注意:它与多对一的区别是维护的关系不同
*多对一维护的关系是:多指向一的关系,有了此关系,加载多的时候可以将一加载上来
*一对多维护的关系是:一指向多的关系,有了此关系,在加载一的时候可以将多加载上来
关键映射代码——在一的一端加入如下标签映射:
[java] view
plain copy
<set name="students">
<key column="classesid"/>
<one-to-many class="com.tgb.hibernate.Student"/>
</set>
缺陷:因为多的一端Student不知道Classes的存在(也就是Student没有维护与Classes的关系)所以在保存Student的时候关系字段classesid是为null的,如果将该关系字段设置为非空,则将无法保存数据,常用解决办法是改用双向关联映射。
五.双向一对多关联映射
采用一对多双向关联映射的目的主要是为了主要是为了解决一对多单向关联的缺陷而不是需求驱动的。
一对多双向关联的映射方式:
* 在一的一端的集合上采用<key>标签,在多的一端加入一个外键
* 在多的一端采用<many-to-one>标签
注意:<key>标签和<many-to-one>标签加入的字段保持一直,否则会产生数据混乱
关键映射代码:
在Classes的一端加入如下标签映射:
[java] view
plain copy
<set name="students"inverse="true">
<key column="classesid"/>
<one-to-many class="com.hibernate.Student"/>
</set>
在Student的一端加入如下标签映射:
[java] view
plain copy
<many-to-one name="classes" column="classesid"/>
inverse属性
* inverse属性可以用在一对多和多对多双向关联上,inverse属性默认为false,为false表示本端可以维护关系,如果inverse为true,则本端不能维护关系,会交给另一端维护关系,本端失效。所以一对多关联映射我们通常在多的一端维护关系,让一的一端失效。
* inverse是控制方向上的反转,只影响存储
一.多对一关联映射
比如用户和组的关系,多个用户可能对应一个组,所以我们就会在“多”的一端加入外键,指向“一”的一端。
1.首先我们会在“多”端的实体中引入“一”端的实体,并生成相应的get,set方法
比如多个用户对应一个分组,我们就会在User实体类中引用Group
private Group group;
public Group getGroup() {
return group;
}
public void setGroup(Group group) {
this.group = group;
}
2.在“多”端的配置文件中添加关系映射,比如在user.hbm.xml中添加标签:
<hibernate-mapping>
<class name="com.bjpowernode.hibernate.User" table="t_user">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<!--维护多对一关系-->
<many-to-one name="group" column="groupid" cascade="save-update"/>
</class>
</hibernate-mapping>
二.单向的一对一关联映射
主键关联
就是让两个实体的主键一样,就不需要加入多余的字段了。比如一个学生对应一个身份证号,一个学生对应一条户口信息等等,都是一对一关联映射。
1、Person实体里要持有IdCard的引用。在Person实体里加入属性:Private IdCard idCard;
2、Person端维护关系,所以需要重点看Person的配置文件,在Person.hbm.xml中,使Person中的Id既为主键又为外键。所以需要修改Person中的id标签:告诉Person里的id去关联哪个实体里的id。
<hibernate-mapping>
<class name="com.tgb.hibernate.Person" table="t_person">
<id name="id">
<!-- 采用foreign生成策略,forgeign会取得关联对象的标识 -->
<generator class="foreign">
<!-- property只关联对象 -->
<param name="property">idCard</param>
</generator>
</id>
<property name="name"/>
<!--
one-to-one指示hibernate如何加载其关联对象,默认根据主键加载
也就是拿到关系字段值,根据对端的主键来加载关联对象
constrained="true表示,当前主键(person的主键)还是一个外键
参照了对端的主键(IdCard的主键),也就是会生成外键约束语句
-->
<one-to-one name="idCard" constrained="true"/>
</class>
</hibernate-mapping>唯一外键关联
外键关联,本来是用于多对一的配置,但是加上唯一的限制之后(采用<many-to-one>标签来映射,指定多的一端unique为true,这样就限制了多的一端的多重性为一),也可以用来表示一对一关联关系,其实它就是多对一的特殊情况。
1、Person.java是实体里有IdCard的引用,即加入属性:private IdCard idCard;IdCard.java里没有Person引用。
2、配置文件:IdCard.hbm.xml里都是普通属性。Person.hbm.xml的主键生成策略为native,使用<many-to-one>标签来维护外键,<many-to-one name="idCard" unique="true"/>。
注意:因为一对一的主键关联映射扩展性不好,当我们的需要发生改变想要将其变为一对多的时候变无法操作了,所以我们遇到一对一关联的时候经常会采用唯一外键关联来解决问题,而很少使用一对一主键关联。
三.双向的一对一关联映射
1、在Person和IdCard里添加对应端的引用,即添加相应属性。
2、在person.hbm.xml中添加<many-to-one>标签
<many-to-one name="idCard" unique="true"/>
在IdCard端新加入如下标签映射:
[java] view
plain copy
<one-to-one name="person"property-ref="idCard"/>
注意:一对一唯一外键关联双向采用<one-to-one>标签映射,必须指定<one-to-one>标签中的property-ref属性为关系字段的名称
四.单向一对多关联映射
一对多关联映射和多对一关联映射的原理是一致的,都是在多的一端加入一个外键,指向一的一端。比如学生和班级的关系:
注意:它与多对一的区别是维护的关系不同
*多对一维护的关系是:多指向一的关系,有了此关系,加载多的时候可以将一加载上来
*一对多维护的关系是:一指向多的关系,有了此关系,在加载一的时候可以将多加载上来
关键映射代码——在一的一端加入如下标签映射:
[java] view
plain copy
<set name="students">
<key column="classesid"/>
<one-to-many class="com.tgb.hibernate.Student"/>
</set>
缺陷:因为多的一端Student不知道Classes的存在(也就是Student没有维护与Classes的关系)所以在保存Student的时候关系字段classesid是为null的,如果将该关系字段设置为非空,则将无法保存数据,常用解决办法是改用双向关联映射。
五.双向一对多关联映射
采用一对多双向关联映射的目的主要是为了主要是为了解决一对多单向关联的缺陷而不是需求驱动的。
一对多双向关联的映射方式:
* 在一的一端的集合上采用<key>标签,在多的一端加入一个外键
* 在多的一端采用<many-to-one>标签
注意:<key>标签和<many-to-one>标签加入的字段保持一直,否则会产生数据混乱
关键映射代码:
在Classes的一端加入如下标签映射:
[java] view
plain copy
<set name="students"inverse="true">
<key column="classesid"/>
<one-to-many class="com.hibernate.Student"/>
</set>
在Student的一端加入如下标签映射:
[java] view
plain copy
<many-to-one name="classes" column="classesid"/>
inverse属性
* inverse属性可以用在一对多和多对多双向关联上,inverse属性默认为false,为false表示本端可以维护关系,如果inverse为true,则本端不能维护关系,会交给另一端维护关系,本端失效。所以一对多关联映射我们通常在多的一端维护关系,让一的一端失效。
* inverse是控制方向上的反转,只影响存储
相关文章推荐
- hibernate基于注解实现映射关系的配置
- Hibernate -- 注解(Annotation)关系映射
- Hibernate关系映射级别注解(一对一双向外键关联、一对一双向外键联合主键)
- Hibernate的核心对象关系映射
- 技术点-hibernate关系映射-多对多单向/双向
- Hibernate 一对多关系映射与一对一关系映射
- hibernate 映射解析——七种映射关系
- 【Hibernate持续更新】映射组件关系
- hibernate 实体关系映射笔记
- Hibernate入门到精通-关系映射一对多
- 在hibernate 中比 SimplePropertyPreFilter 还要好用的过滤类 ComplexPropertyPreFilter(级联过滤,关系映射过滤类,复杂的属性预过滤器)!!!!
- Hibernate 基于注解的方式 实现的关系映射案例(一对一关系,一对多关系,多对多关系)
- Hibernate-----关系映射 重点!!!
- hibernate-关系映射一对多(多对一)双向关联)-10
- 在使用Hibernate时,因为一个查询需要更多的表连接而要使用SQL来解决性能问题。然而返回的结果集中包含了没有映射的Entity类中的表字段,在这个SQL中还有使用如何将层次关系的父子结点显示为横行
- Hibernate关系映射(四)一对多单向关联@OneToMany Annotation方式
- Hibernate 关系映射(6) 基于中间表关联的单向1:N
- Hibernate【关系映射-左内右连接】
- Hibernate中,One2One映射关系的XML实现方式
- Hibernate对象-关系映射基础