hibernate一对一双向关联映射
映射原理
双向关联映射与单向关联映射的原理是一样的,双向关联映射并不影响存储,只影响加载。所以,双向关联映射和单向关联映射的关系模型是一样的即数据库的表结构是一样的,只是IdCard的实体类和配置文件(IdCard.hbm.xml)发生了一点点变化。
对象模型
从上图中可以看出:
1、一个人只有一张身份证,唯一的一个身份证号,对象之间是一对一的关系;
2、两个对象得关系维护还是由person端决定(因为关系只能由一端维护主键,否则关系就乱了)。
根据上面的对象模型,我们可以看到Person端没有变化,但是要在IdCard端加上Person的引用。
无论是单向关联映射还是双向关联映射,他们都属于一对一关联映射,只是他们主键的生成策略不同,分为主键关联映射和唯一外键关联映射。
由于它们都属于一对一关联映射,所以,Hibernate封装双向关联映射时,主键关键映射和唯一外键关联映射的加载策略一样,都采用的是一对一<one-to-one name=""></one-to-one>,只是属性设置不一致,所以,下面我们分开来看IdCard的配置文件。
分类:
一、主键关联映射
同一对一单向关联映射类似,主键关联即利用主键进行关联,关联主键的值相同。下面我们看一下映射文件:
IdCard.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 package="com.liang.hibernate"> <class name="IdCard" table="t_idCard"> <id name="id"> <generator class="native"></generator> </id> <property name="cardNo"></property> <!-- 怎么加载对象,抓取策略:join联合查询(默认),select:一条条的查询 --> <one-to-one name="person" class="Person" fetch="join"></one-to-one> </class> </hibernate-mapping>
Person.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 package="com.liang.hibernate"> <class name="Person" table="t_person"> <id name="id"> <!-- 采用foreign生成策略,forgeign会取得关联对象的标识 --> <generator class="foreign" > <param name="property">idCard</param> </generator> </id> <property name="name"></property> <!-- one-to-one指示hibernate如何加载其关联对象,默认根据主键加载 也就是拿到关系字段值,根据对端的主键来加载关联对象 constrained="true"表示,当前主键(person的主键)还是一个外键 参照了对端的主键(IdCard的主键),也就是会生成外键约束语句 --> <one-to-one name="idCard" class="IdCard" constrained="true"></one-to-one> </class> </hibernate-mapping>
生成的表结构
二、唯一外键关联映射
一对一双向关联映射的外键关联映射也与一对一单向关联映射的外键关联映射类似,在其一对一的指向端(Person)存在一个唯一外键,该唯一外键与被指向端(IdCard)相关联,关联主键的值相同。下面我们看一下映射文件:
IdCard.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 package="com.liang.hibernate"> <class name="IdCard" table="t_idCard"> <id name="id"> <generator class="native"></generator> </id> <property name="cardNo"></property> <!-- 一对一唯一外键关联双向采用<one-to-one>标签来映射,必须指定<one-to-one> 标签中的property-ref属性为关系字段的名称 --> <one-to-one name="person" class="Person" property-ref="idCard"></one-to-one> </class> </hibernate-mapping>
Person.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 package="com.liang.hibernate"> <class name="Person" table="t_person"> <id name="id"> <generator class="native" ></generator> </id> <property name="name"></property> <!-- 由于它是一对一的唯一外键关联,它是多对一关联的特例,注释可以直接写成多对一关联--> <!-- idCard属性,表达的是本对象与IdCard的多对一关系。 --> <many-to-one name="idCard" class="IdCard" column="idCardId" unique="true"></many-to-one> </class> </hibernate-mapping>
生成的表结构
对比
一对一单向和双向关联映射的区别正是对象模型和关系模型的区别之一。
对象模型:有方向性。它到底是单向还是双向是由对象模型决定的即配置文件决定。
关系模型:没有方向性或者说是双向的。从任何一端都可以加载另一端。
总结
一对一双向关联映射并不是必须的,是由需求下决定的。如果没有这样的需求,用户也没有要求,系统也不需要,就没有必要建立双向的关联映射。