双向关联一对一映射详解(2)

本文详细介绍了在对象模型中如何实现双向外键关联,包括一对一关系的映射配置及SQL生成,展示了通过Hibernate进行双向关联的具体操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

二、双向外键关联


        双向的外键关联可以理解为外键关联的一种特殊情况,这种特殊主要是由于它是一种双向的对应关系,在前篇文章中提到如果想要在一张表中添加一个外键字段的话可以使用<many-to-one>标签,它会关系模型中生成对应的外键列。这里想要实现双向的外键关联就必须使用该标签。


  1、对象模型


        先来看对象模型,人和身份证属于一对一的关系,一个人对应着一个身份,所以它们之间的多重性是一对一的,并且这种对应关系是双向的。所以它的对象模型同双向主键一对一是相同的,如下图:


    2、关系模型


        对应的关系模型会发生很大的变化,一对一的外键关联关系会在一张表中生成对应的外键,拿到人和身份证上来说也就是人的关系模型中会有一个身份证号的主键列,它们之间形成了双向的一对一的情况,如下图:


         它们之间的对应关系就是上图中看到的,person表中有idCard表的主键,形成了一对一的外键关联关系,而且是双向的,也就是说通过person能够获取到idCard,另外通过idCard也能获取到person。

         Person对象和IdCard对象内的代码同上篇文章中的对象代码一致,不在做代码罗列,唯一不同的是映射文件中的配置问题。


   3、映射文件


         idCard.hbm.xml映射文件,idCard表不是映射的主表,所以在做一对一的映射时需要使用的是<one-to-one>标签来配置,并且需要制定person关系模型中的外键属性,具体代码如下:


  1. <?xml version="1.0"?>  
  2. <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
  3. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
  4. <!-- Generated 2014-5-18 22:27:43 by Hibernate Tools 3.4.0.CR1 -->  
  5. <hibernate-mapping>  
  6.     <class name="com.src.hibernate.IdCard" table="IDCARD">  
  7.         <id name="id" type="int">  
  8.             <generator class="native" />  
  9.         </id>  
  10.         <property name="cardNo" type="java.lang.String">  
  11.             <column name="CARDNO" />  
  12.         </property>  
  13.           
  14.         <one-to-one name="person" property-ref="idCard"></one-to-one>  
  15.     </class>  
  16. </hibernate-mapping>  

        Person.hbm.xml映射文件,person表是映射的主表,需要在该表中添加一个外键属性列来标示idCard表,所以这里需要使用<many-to-one>标签,在person对象中生成相应的外键,并且还要使用unique标明属性唯一。

  1. <?xml version="1.0"?>  
  2. <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
  3. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
  4. <!-- Generated 2014-5-18 22:27:43 by Hibernate Tools 3.4.0.CR1 -->  
  5. <hibernate-mapping>  
  6.     <class name="com.src.hibernate.Person" table="PERSON">  
  7.         <id name="id" type="int" column="personId">  
  8.             <generator class="native" />  
  9.         </id>  
  10.         <property name="name" type="java.lang.String">  
  11.             <column name="NAME" />  
  12.         </property>  
  13.           
  14.         <many-to-one name="idCard" column="idCardNo" unique="true" not-null="true"></many-to-one>  
  15.     </class>  
  16. </hibernate-mapping>  

      对象的映射文件配置完成,接下来生成关系模型,SQL语句如下:
  1. alter table PERSON drop foreign key FK8C768F55794A52CA  
  2. drop table if exists IDCARD  
  3. drop table if exists PERSON  
  4. create table IDCARD (id integer not null auto_increment, CARDNO varchar(255), primary key (id))  
  5. create table PERSON (personId integer not null auto_increment, NAME varchar(255), idCardNo integer not null uniqueprimary key (personId))  
  6. alter table PERSON add index FK8C768F55794A52CA (idCardNo), add constraint FK8C768F55794A52CA foreign key (idCardNo) references IDCARD (id)  

        生成的SQL语句首先是创建的表,在建表时指定了主键列,创建完成后修改了两个表指定外键属性,形成一对一的关系。
         编写测试方法,采用单元测试,加载两个类的对象,并分别从对象的一端获取另一个对象

  1. //加载对象,使用IdCard对象装载person对象  
  2. public void testLoad1(){  
  3.     Session session=null;  
  4.       
  5.     try{  
  6.         session=HibernateUtils.getSession();  
  7.         session.beginTransaction();  
  8.           
  9.         //获取IdCard对象,在IdCard中获取与该对象唯一关联的person对象  
  10.         IdCard idcard=(IdCard)session.load(IdCard.class,1);  
  11.         System.out.println("person.Id= "+idcard.getPerson().getId());  
  12.         System.out.println("idCard.person.name= "+idcard.getPerson().getName());  
  13.           
  14.         //获取Person对象,在Person对象中获取与它唯一关联的IdCard对象  
  15.         Person person=(Person)session.load(Person.class,1);  
  16.         System.out.println("idCard.id: "+person.getIdCard().getId());  
  17.         System.out.println("idCard.cardNo: "+person.getIdCard().getCardNo());  
  18.           
  19.         //提交事务  
  20.         session.getTransaction().commit();  
  21.     }catch(Exception e){  
  22.         e.printStackTrace();  
  23.         session.getTransaction().rollback();  
  24.     }finally{  
  25.         HibernateUtils.closeSession(session);  
  26.     }  
  27. }  

        生成的内容:



        对比两种映射关系,主键和外键两种映射,都是双向的映射关系,需要在对象的两端同时配置映射关系,不同的是主键只需要使用<one-to-one>因为它不需要生成属性列,但是必须对表的主键采用foreign的主键生成策略,并标示外键对象;外键的生成策略则需要采用<many-to-one>标签来生成新的外键列。


结语


      双向关联中的一对一映射至此已经讨论完成,两篇文章主要讨论了双向关联中的两种用法,其实还是很简单的,记住一句话想要生成外键就使用<many-to-one>标签,如果唯一那就添加unique属性,<one-to-one>标签只是指明了一对一的关系它只是指明一个对象如何加载另一个对象并不在关系模型中添加新列。下篇文章将会对一对多关联展开讨论。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值