系列文章目录
一对一映射
- 系列文章目录
- 前言
- 一、一对一映射是什么?
- 二、一对一单向关联
- ①一对一主键关联映射
- ②一对一唯一外键映射
- 三、一对一双向关联
- ①一对一主键关联映射(双向关联Person<----->IdCard)
- ②h一对一唯一外键关联映射(双向关联Person<----->IdCard)
- 总结
前言
由于公司项目上进行面向对象的架构设计对于ORM部分使用的是Spring Data JPA框架。将ORM完全交给Spring Data JPA框架,而Hibernate是Spring Data JPA的实现方式之一,通过对HIbernate框架的学习能够更好的理解ORM框架,以及Spring Data JPA框架。
下面的博客是对于Hibernate框架中的基本映射中的一对一映射进行的实践,总结的并不全面,旨在对于一对一映射关系有一个宏观了解并能够进行基本运用。
一、一对一映射是什么?
一对一映射是指两个实体之间存在一对一的关系,其中一个实体与另一个实体关联的方式是通过共享相同的主键或唯一键来建立关系。
关联关系整体上分为两大类,分为单向关联及我知道你,而你不知道我,双向关联双方都知道彼此。在一对一映射中单向关联分为:一种方式是一对一主键关联映射另一种方式是一对一唯一外键关联映射。一对一双向关联也是如此。
二、一对一单向关联
案例:现在有两个实体Person实体和IdCard。
package com.wangwei.hibernate;
public class Person {
private int id;
private String name;
private IdCard idCard;
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 IdCard getIdCard() {
return idCard;
}
public void setIdCard(IdCard idCard) {
this.idCard = idCard;
}
}
package com.wangwei.hibernate;
public class IdCard {
private int id;
private String cardNo;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCardNo() {
return cardNo;
}
public void setCardNo(String cardNo) {
this.cardNo = cardNo;
}
}
①一对一主键关联映射
我将人查出来我要能够看到身份证信息,通过唯一主键进行关联。
示意图:
使用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.wangwei.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>
<?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.wangwei.hibernate.IdCard" table="t_idCard">
<id name="id">
<generator class="native"/>
</id>
<property name="cardNo"/>
</class>
</hibernate-mapping>
最终生成的表结构
②一对一唯一外键映射
①和②相比较建议使用②,②可以更改为多对一映射(一对一唯一外键映射,是多对一映射关系的特例)
示意图
在Person中添加idCard字段
使用XML配置方式定义一对一主键映射
实体IdCard对应的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.wangwei.hibernate.Person" table="t_person">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<!-- 采用<many-to-one>标签来映射,指定多的一端unique为true,这样就限制了多的一端的多重性
为一 -->
<many-to-one name="idCard" unique="true"/>
</class>
</hibernate-mapping>
生成的表结构
三、一对一双向关联
①一对一主键关联映射(双向关联Person<----->IdCard)
需要在IdCard加入标签,指示hibernate将关联对象Person
根据主键加载上来
不影响存储,只影响加载
在实体IdCard中声明Person类型的属性
package com.wangwei.hibernate;
public class IdCard {
private int id;
private String cardNo;
private Person person;
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCardNo() {
return cardNo;
}
public void setCardNo(String cardNo) {
this.cardNo = cardNo;
}
}
示意图
使用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.wangwei.hibernate.IdCard" table="t_idCard">
<id name="id">
<generator class="native"/>
</id>
<property name="cardNo"/>
<one-to-one name="person"/>
</class>
</hibernate-mapping>
<?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.wangwei.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>
生成的表结构
②h一对一唯一外键关联映射(双向关联Person<----->IdCard)
一对一唯一外键关联双向采用标签映射,必须指定
标签中的property-ref属性为关系字段的名称
在实体IdCard中声明Person类型的属性
package com.wangwei.hibernate;
public class IdCard {
private int id;
private String cardNo;
private Person person;
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCardNo() {
return cardNo;
}
public void setCardNo(String cardNo) {
this.cardNo = cardNo;
}
}
使用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.wangwei.hibernate.IdCard" table="t_idCard">
<id name="id">
<generator class="native"/>
</id>
<property name="cardNo"/>
<one-to-one name="person" property-ref="idCard"/>
</class>
</hibernate-mapping>
<?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.wangwei.hibernate.Person" table="t_person">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<many-to-one name="idCard" unique="true"/>
</class>
</hibernate-mapping>
生成的表结构
总结
- 一对一映射可用于将相关实体进行关联,保证关联的一对一关系的数据完整性和一致性。
- 我们通过一对一映射将实体进行关联之后,特别时在进行查询的时候,可以查询出该实体所关联到的实体。