一对一关联关系
一对一关联关系在Hibernate5中的实现方式有两种:主键关联和外键关联。
1、主键关联
主键关联的重点:关联的两个表共享一个主键值,例如,一个单位在网上的一个系统中注册为会员,则会员有一个登陆账号,单位注册为会员的数据保存在表company中,每个会员的登陆账号保存在表login中;一个会员只有一个登陆账号,一个登陆账号只属于一个会员,两个表之间是一对一的对应关系。
两个表company和login对应的持久化对象分别为Company和Login,表之间是一对一的关系。他们共用一个主键值id,这个主键可由company表或者login表生成。
为了表示Company与Login之间的一对一关联关系,在Company与Login的映射文件Company.hbm.xml和Login.hbm.xml中都要使用 one-to-one 标记,代码如下所示:
Conpany.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- 解析文件的DTD -->
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- 映射文件的根目录 -->
<hibernate-mapping package="PO">
<class name="Company" table="company">
<id column="ID" name="id" type="integer">
<!-- 自增 -->
<generator class="identity"></generator>
</id>
<property name="companyname" column="COMPANYNAME" type="string"></property>
<property name="linkman" column="LINKMAN" type="string"></property>
<property name="telephone" column="TELEPHONE" type="string"></property>
<property name="email" column="EMAIL" type="string"></property>
<!-- 映射Company与Login的一对一主键关联 -->
<one-to-one name="login" cascade="all" class="PO.Login" lazy="false"
fetch="join" outer-join="true"></one-to-one>
</class>
</hibernate-mapping>
下面我再来对one-to-one中的一些属性进行一些解析:
(1)、lazy属性
lazy属性设定为true,表示延迟加载;设定为false,则表示立即加载。
延迟加载:表示Hibernate5在从数据库中取得数据组装好一个对象后,不会立即再从数据库取得数据组装此对象所关联的对象,而是等到需要的时候,才从数据库取得数据组装此关联对象。
立即加载:表示Hibernate5在从数据库中取得数据组装好一个对象后,会立即在从数据库去取得数据组装此对象所关联的对象。
(2)、cascade属性
该属性表明操作是否从父对象级联到被关联对象,它的取值可以有以下几种:
- none:在保存、删除或修改对象的时候,不对其附属对象(关联对象)进行级联操作。这是默认设置。
- save-update:在保存、更新当前对象时,级联保存、更新附属对象(临时对象、游离对象)。
- delete:在删除当前对象时,级联删除附属对象。
- all:所有情况下均进行级联操作,即包括save-update和delete操作。
- delete-orphan:删除和当前对象解除对象的附属对象。
(3)fetch属性
该属性的可选值是join和select,默认值为select。
当fetch属性设定为join时,表示连接抓取(Hibernate5通过在select语句中使用外连接来获得对象的关联实例或者关联集合)。
当fetch属性设定为select时,表示查询抓取(需要另外发送一条select语句抓取当前对象的关联实体或集合)。
Login.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- 解析文件的DTD -->
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- 映射文件的根目录 -->
<hibernate-mapping package="PO">
<class name="Login" table="login">
<id column="ID" name="id" type="integer">
<generator class="foreign">
<param name="property">company</param>
</generator>
</id>
<property name="loginname" column="LOGINNAME" type="string"></property>
<property name="loginpwd" column="LOGINPWD" type="string"></property>
<!-- 映射Company与Login的一对一关联 -->
<one-to-one name="company" class="PO.Company" constrained="true"></one-to-one>
</class>
</hibernate-mapping>
Login.hbm.xml的主键id使用外键(foreign)生成机制,引用表company的主键作为login表的主键值。company在该映射文件的one-to-one 元素中进行了定义,它是Company对象的代号。one-to-one元素的属性constrained=“true” 表示login引用了company的主键作为外键。
2、外键关联
外键关联的要点:两个表各自有不同的主键,但其中一个表有一个外键引用另一个表的主键。例如,客户(Client)和客户地址(Address)是外键关联的一对一关系,他们在数据库中对应的表分别为client和address表。
Address.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- 解析文件的DTD -->
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- 映射文件的根目录 -->
<hibernate-mapping package="PO">
<class name="Address" table="address">
<id column="ID" name="id" type="integer">
<generator class="identity"></generator>
</id>
<property name="province" column="PROVINCE" type="string"></property>
<property name="city" column="CITY" type="string"></property>
<property name="street" column="STREET" type="string"></property>
<property name="zipcode" column="ZIPCODE" type="string"></property>
<!-- 映射Client与Address的一对一外键关联 -->
<one-to-one name="Client" class="PO.Client" property-ref="address"></one-to-one>
</class>
</hibernate-mapping>
Client.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- 解析文件的DTD -->
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- 映射文件的根目录 -->
<hibernate-mapping package="PO">
<class name="Client" table="client">
<id column="ID" name="id" type="integer">
<generator class="identity"></generator>
</id>
<property column="CLIENTNAME" name="clientname" type="string"></property>
<property column="PHONE" name="phone" type="string"></property>
<property column="EMAIL" name="email" type="string"></property>
<!-- 映射Client到Address的一对一外键关联,唯一的多对一,实际上变成了一对一关系 -->
<many-to-one name="address" class="PO.Address" column="address" cascade="all"
lazy="false" unique="true"></many-to-one>
</class>
</hibernate-mapping>
many-to-one 元素的name属性声明外键关联对象的代号,class属性声明该外键关联对象的类,column属性声明该外键在数据表中对应的字段名,unique属性表示使用DDL为外键字段生成一个唯一的标识。