(Hibernate进阶)Hibernate映射——一对一单向关联映射(五)

映射原理

两个实体对象之间是一对一的关联映射,即一个对象只能与另外唯一的一个对象相对应。例如:一个人(Person)只有一张身份证(IdCard)。我们看一下这个例子的对象模型,如下图所示:

对象模型

(Hibernate进阶)Hibernate映射——一对一单向关联映射(五)

从上图中可以看出:

1、一个人只有一张身份证,唯一的一个身份证号,对象之间是一对一的关系;

2、人(Person)持有身份证(IdCard)的引用,所以,两个对象关系维护由person端决定。

从对象模型映射成关系模型,有两种方式:主键关联和唯一外键关联,我们继续看下面的内容。

分类:

主键关联:

1、两个实体对象的主键一样,以表明它们之间的一一对应关系;

2、不需要多余的外键字段来维护关系,仅通过主键来关联,即Person的主键要依赖IdCard的主键,他们共用一个主键值。

以上两点恰与唯一外键关联相反。

 主键关联的关系模型

(Hibernate进阶)Hibernate映射——一对一单向关联映射(五)

Person.hbm.xml

  1. <?xml version="1.0"?>
  2. <!DOCTYPE hibernate-mapping PUBLIC
  3. "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
  4. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
  5. <hibernate-mapping package="com.liang.hibernate">
  6. <class name="Person" table="t_person">
  7. <id name="id">
  8. <!-- 采用foreign生成策略,forgeign会取得另外一个关联对象的标识 -->
  9. <generator class="foreign" >
  10. <param name="property">idCard</param>
  11. </generator>
  12. </id>
  13. <property name="name"></property>
  14. <!--
  15. one-to-one指示hibernate如何加载其关联对象,默认根据主键加载
  16. 也就是拿到关系字段值,根据对端的主键来加载关联对象
  17. constrained="true"表示约束,当前主键(person的主键)还是一个外键
  18. 参照了对端的主键(IdCard的主键),也就是会生成外键约束语句
  19. -->
  20. <!-- idCard属性,表达的是本对象与IdCard的一对一关系。 -->
  21. <one-to-one name="idCard" class="IdCard"  constrained="true"></one-to-one>
  22. </class>
  23. </hibernate-mapping>

生成的表结构以及测试数据:

(Hibernate进阶)Hibernate映射——一对一单向关联映射(五)(Hibernate进阶)Hibernate映射——一对一单向关联映射(五)

唯一外键关联:

1、两个实体对象用一个外键来关联,以表表明对象之间的关系。

2、其实它是多对一关联映射的特例,多的一端加上唯一的限制之后,用来表示一对一的关联关系。

所以它采用多对一的标签来映射,如下所示:

  1. <!-- 采用<mang-to-one>标签来映射,指定多的一端unique为true,
  2. 这样就限制了多的一端的多重性为一,就是这样来映射的。
  3. -->
  4. <many-to-one name="" unique="true"></many-to-one>

唯一外键的关系模型

(Hibernate进阶)Hibernate映射——一对一单向关联映射(五)

Person.hbm.xml

  1. <?xml version="1.0"?>
  2. <!DOCTYPE hibernate-mapping PUBLIC
  3. "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
  4. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
  5. <hibernate-mapping package="com.liang.hibernate">
  6. <class name="Person" table="t_person">
  7. <id name="id">
  8. <generator class="native" ></generator>
  9. </id>
  10. <property name="name"></property>
  11. <!-- 由于它是一对一的唯一外键关联,它是多对一关联的特例,注释可以直接写成多对一关联-->
  12. <!-- idCard属性,表达的是本对象与IdCard的多对一关系。 -->
  13. <many-to-one name="idCard" class="IdCard" column="idCardId" unique="true"></many-to-one>
  14. </class>
  15. </hibernate-mapping>

生成的表结构以及测试数据:

(Hibernate进阶)Hibernate映射——一对一单向关联映射(五)(Hibernate进阶)Hibernate映射——一对一单向关联映射(五)

其他相同代码如下:

Person

  1. public class Person {
  2. private int id;
  3. private String name;
  4. private IdCard idCard;
  5. public IdCard getIdCard() {
  6. return idCard;
  7. }
  8. public void setIdCard(IdCard idCard) {
  9. this.idCard = idCard;
  10. }
  11. public int getId() {
  12. return id;
  13. }
  14. public void setId(int id) {
  15. this.id = id;
  16. }
  17. public String getName() {
  18. return name;
  19. }
  20. public void setName(String name) {
  21. this.name = name;
  22. }
  23. }

IdCard

  1. public class IdCard {
  2. private int id;
  3. private String cardNo;
  4. public int getId() {
  5. return id;
  6. }
  7. public void setId(int id) {
  8. this.id = id;
  9. }
  10. public String getCardNo() {
  11. return cardNo;
  12. }
  13. public void setCardNo(String cardNo) {
  14. this.cardNo = cardNo;
  15. }
  16. }

IdCard.hbm.xml

  1. <?xml version="1.0"?>
  2. <!DOCTYPE hibernate-mapping PUBLIC
  3. "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
  4. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
  5. <hibernate-mapping package="com.liang.hibernate">
  6. <class name="IdCard" table="t_idCard">
  7. <id name="id">
  8. <generator class="native"></generator>
  9. </id>
  10. <property name="cardNo"></property>
  11. </class>
  12. </hibernate-mapping>

建议

由于一对一主键关联映射具有以下两个缺点:

1、灵活性差,没有办法改成多对一关联映射,不能应变多变的需求;

2、必须先保存关联对象IdCard,之后才能保持Person;

所以,在映射一对一单向关联映射时,我们采用唯一外键关联映射。

上一篇:利用ChainMap进行多字典合并


下一篇:比赛题目训练系列03 (2020 ICPC Universidad Nacional de Colombia Programming Contest)