一对一的映射在对象模型中是常常见到的,为了将对象模型转换为关系模型就必须在映射文件里进行配置,上篇文章讨论了一对一映射的单向关联的情况,重点是<one-to-one>标签的使用,须要在映射的主对象中加入该标签,并将该对象的主键设置为foreign这样就实现了主键关联映射。讨论完了单向接下来讨论双向映射。

一、双向主键关联

双向的主键关联事实上是单向一对一主键关联的一种特殊情况。仅仅只是要在关联对象的两端的映射文件里都要进行<one-to-one>的配置。另外还要在主映射的主键一端採用foreign外键关联属性。

这里相同使用Person和IdCard来讨论,一个人相应着一个唯一的身份证,并且一个身份证也唯一映射着一个人。所以这就产生了双向的关联关系。Person的主键相同也是IdCard的主键,各自是主键的同一时候也是外键,这样的关联关系成为双向一对一映射。表现到关系模型中可例如以下图:

图中的两个表採用了主键关联,person的主键是idCard的主键。所以它们之间构成了朱外键的约束关系,而且保证唯一性,映射到对象模型中。转变为person类和idCard类的一对一关系。例如以下图:

这样的一对一的关系上篇文章中也有讲到用的是<one-to-one>标签,另外这样的一对一映射又是双向的,所以要在两个对象之间同一时候配置<one-to-one>,首先来看idCard相应的类代码和映射文件代码。

1、IdCard相应的信息

IdCard.java类,IdCard类和Person类之间有一对一的关联关系所以要在IdCard类中加入相应的Person属性。这是为了能在映射文件里的外键中加入相应的属性,设置相应的外键关联类。

package com.src.hibernate;public class IdCard {//id属性private int id;public int getId() {return id;}public void setId(int id) {this.id = id;}//卡号属性private String cardNo;public String getCardNo() {return cardNo;}public void setCardNo(String cardNo) {this.cardNo = cardNo;}//卡号相应的人private Person person;public Person getPerson(){return person;}public void setPerson(Person person){this.person=person;}
}

IdCard.hbm.xml映射文件。在映射文件里加入外键属性person。并加入相应的<one-to-one>标签。目的是强制约束person类来实现一对一的映射关系,最后在映射中将constrained属性设为true,保证强制约束关系。

<?

xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <!-- Generated 2014-5-15 23:47:00 by Hibernate Tools 3.4.0.CR1 --> <hibernate-mapping> <class name="com.src.hibernate.IdCard" table="IDCARD"> <id name="id" type="int" column="personId"> <generator class="foreign"> <param name="property">person</param> </generator> </id> <property name="cardNo" type="string" column="cardno"></property> <one-to-one name="person" constrained="true"></one-to-one> </class> </hibernate-mapping>

2、Person相应的信息

Person.java类。在该类中除了加入主要的属性外还要加入相应的IdCard类作为属性,由于它们之间是一对一的双向关联关系,所以在Person类中相同要加入IdCard类,相同的道理IdCard类中相同加入了Person类属性。

package com.src.hibernate;public class Person {//id号private int id;public int getId() {return id;}public void setId(int id) {this.id = id;}//姓名private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}//idCardprivate IdCard idcard;public IdCard getIdcard() {return idcard;}public void setIdcard(IdCard idcard) {this.idcard = idcard;}
}

Person.hbm.xml映射文件,该文件里主键生成策略没有特殊的要求。由于它和IdCard类相互制约的关系,它的主键和外键都是IdCard的主键,另外由于是一对一关系所以要在映射文件里加入<one-to-one>标签来标示。

<?

xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <!-- Generated 2014-5-15 23:47:00 by Hibernate Tools 3.4.0.CR1 --> <hibernate-mapping> <class name="com.src.hibernate.Person" table="PERSON"> <id name="id" type="int" column="personId"> <generator class="native"></generator> </id> <property name="name" type="string" column="personName"></property> <!-- one-to-one标签指示Hibernate怎样载入其关联对象。默认依据主键载入,也就是拿到关系字段值,依据对端的主键来载入关联对象 --> <one-to-one name="idcard"></one-to-one> </class> </hibernate-mapping>

3、Hibernate映射文件

上面的类和映射文件配置好后接下来要在Hibernate.cfg.xml中配置与数据库映射的信息。须要将两个配置文件加入到Hibernate配置文件里。这样在生成相应的数据库时才干找到相应的生成项。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC"-//Hibernate/Hibernate Configuration DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration><session-factory><property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property><property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate_one2one_pk1</property><property name="hibernate.connection.username">root</property><property name="hibernate.connection.password">1234</property><property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property><mapping resource="com/src/hibernate/Person.hbm.xml"/><mapping resource="com/src/hibernate/IdCard.hbm.xml" ></mapping></session-factory>
</hibernate-configuration>

4、生成结果

配置完毕后就能够将上面的内容生成对应的数据库了,在数据库中它会依照配置的内容生成对应的表结构,在表中有对应的外键和主键字段。生成表结构时Hibernate会在控制台输出对应的SQL语句,例如以下:

alter table IDCARD drop foreign key FK806F76ABAC038CD8
drop table if exists IDCARD
drop table if exists PERSON
create table IDCARD (personId integer not null, cardno varchar(255), primary key (personId))
create table PERSON (personId integer not null auto_increment, personName varchar(255), primary key (personId))
alter table IDCARD add index FK806F76ABAC038CD8 (personId), add constraint FK806F76ABAC038CD8 foreign key (personId) references PERSON (personId)

生成的表结构例如以下图:

在两张表中同一时候生成了personId主键,而且也是对应的外键,它同一时候限制约束了两张表的主键同样且唯一。

5、写入载入測试

生成表后測试下对表的写入和从表中读取数据,编写相应的測试类,測试採用的是单元測试。编写相应的測试方法。

5.1 写入測试

在写入到数据库时一定要注意写入的两个对象都要转化到相应的Trainent状态,否则会出现状态转化的错误,測试代码例如以下: 
public void testSave1(){Session session=null;try{//创建一个会话对象session=HibernateUtils.getSession();//开启会话事务session.beginTransaction();//创建person对象,并保存Person person=new Person();person.setName("zhangsan");session.save(person);//创建idCard对象,并保存IdCard idcard=new IdCard();idcard.setCardNo("1111111111111");idcard.setPerson(person);session.save(idcard);//提交事务,改动数据库session.getTransaction().commit();}catch(Exception e){//打印错误信息e.printStackTrace();//业务回滚session.getTransaction().rollback();}finally{//关闭会话HibernateUtils.closeSession(session);}
}

插入的数据例如以下图:

5.2 载入測试

编写载入方法,由于关联关系是双向的。所以相应的载入操作应该是通过一端载入还有一端,也就是获取相应的Person类,并通过Person类来获取相应的IdCard信息。相反的也要成立,代码例如以下:
public void testLoad1(){Session session=null;try{//创建一个会话对象session=HibernateUtils.getSession();//开启会话事务session.beginTransaction();//获取person对象,并保存Person person=(Person)session.load(Person.class,5);System.out.println("IdCard.Id: "+person.getIdcard().getId());System.out.println("IdCard.cardno: "+person.getIdcard().getCardNo());//创建idCard对象,并保存IdCard idcard=(IdCard)session.load(IdCard.class, 5);System.out.println("Person.Id: "+idcard.getPerson().getId());System.out.println("Person.name: "+idcard.getPerson().getName());//提交事务。改动数据库session.getTransaction().commit();}catch(Exception e){//打印错误信息e.printStackTrace();//业务回滚session.getTransaction().rollback();}finally{//关闭会话HibernateUtils.closeSession(session);}
}

执行以上測试方法,在控制台打印的相关内容例如以下:

结语

   文章对双向关联关系做了具体的讨论。重点在于分析这样的双向一对一关系的建立及应用。双向的一对一关系分为主键和外键两种,本文主要讨论了主键的约束关系,这样的约束关系同一时候採用了<one-to-one>和<many-to-one>,下文将会具体讨论外键关联。

【Hibernate步步为营】--双向关联一对一映射具体解释(一)相关推荐

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

    一.双向主键关联 双向的主键关联其实是单向一对一主键关联的一种特殊情况,只不过要在关联对象的两端的映射文件中都要进行<one-to-one>的配置,另外还要在主映射的主键一端采用forei ...

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

    二.双向外键关联 双向的外键关联可以理解为外键关联的一种特殊情况,这种特殊主要是由于它是一种双向的对应关系,在前篇文章中提到如果想要在一张表中添加一个外键字段的话可以使用<many-to-one ...

  3. 【Hibernate步步为营】--多对多映射详解

    上篇文章详细讨论了一对多映射,在一对多映射中单向的关联映射会有很多问题,所以不建议使用如果非要采用一对多的映射的话可以考虑使用双向关联来优化之间的关系,一对多的映射其实质上是在一的一端使用<ma ...

  4. Hibernate基于主键一对一映射操作实例

    背景: 公民和公民的身份证,是一个一对一的例子,一个公民只有一个身份证. 这个是基于主键的,基于外键的映射在:http://blog.csdn.net/nthack5730/article/detai ...

  5. 【Hibernate步步为营】--关联映射之多对一

    上篇文章讨论了Hibernate的基本映射,一个实体类对应着一张表,在相应的Hibernate Mapping文件中使用<class>标签映射.并且实体类中的普通属性对应着表字段,使用&l ...

  6. Hibernate(六)一对一映射关系

    One to One 映射关系(只有当映射自定义对象时,才会用,hibernate支持的java类型都可直接设成属性,了解第一和第二种的xml即可) 基于外键的单向一对一 (xml和annotatio ...

  7. 【Hibernate步步为营】--映射合集汇总

    前几篇文章详细讨论了对象模型到关系模型的转化方法,对映射关系做了详细的了解,Hibernate将对象模型转化为相应的关系模型是通过使用相应的映射来完成的(同样也可以使用注解),对于对象之间的关系的转化 ...

  8. Hibernate一对多单向关联和双向关联映射方法及其优缺点

    一对多关联映射和多对一关联映射实现的基本原理都是一样的,既是在多的一端加入一个外键指向一的一端外键,而主要的区别就是维护端不同. 它们的区别在于维护的关系不同: 一对多关联映射是指在加载一的一端数据的 ...

  9. 【Hibernate步步为营】--(一对多映射)之单向关联

    上篇文章讨论了双向关联的一对一映射,用了两个章节.主要是从主键和外键两种关联映射展开具体讨论.双向关联的映射须要在两个映射文件里分别加入相互的相应关系,斌刚在相应的类中加入相应的关联类的属性,这样在一 ...

最新文章

  1. 适合做生物信息的笔记本推荐
  2. DHCP企业应用指南
  3. Android通过Scheme协议打开APP界面
  4. DataWhale sklearn学习笔记(一)
  5. IDEA创建Servlet项目
  6. 【labelme】改造labelme
  7. 求最长上升子序列(Lis模板)
  8. 基于FPGA实现SDI接口
  9. python保存不了_新手,我的python保存不了文件
  10. The 46th ICPC Asia Jinan Regional Contest,2021,46届济南站热身赛
  11. Python 3.4中文编码
  12. 安装Ubuntu最后重启出错Write through
  13. svn 1.12.0 版本以及汉化包(百度网盘分享--永久有效)
  14. [unity3d插件]插件效果以及下载
  15. ei加声调怎么加_微商怎么加好友找客源实操篇
  16. VC dxgi 截屏保存bmp文件
  17. 使用Labwindows开发DAQmx
  18. 1+1备份和1:1冗余备份区别
  19. 如何在阿里云服务器上安装爱快软路由系统
  20. HNU JAVA 导弹防御系统

热门文章

  1. 火星上的甲烷从哪里来,科学家用算法给出了答案
  2. 小鹏发布会上硬刚特斯拉AutoPilot:有视频有真相,特斯拉不懂中国路况
  3. 硬件厂商纷纷“变软”:FPGA行业巨头Xilinx推出Vitis AI平台,并在GitHub上开源
  4. GitHub回应突然断供:身在美国不由己,无权提前通知预警
  5. 微软公布19财年财报:净利润增长22%,云计算首超个人计算业务
  6. 从终端运行python程序
  7. 反向区域DNS解析服务
  8. java连接redis无法连接,报异常RedisConnectionException
  9. Java并发编程:线程池
  10. 第5章 案例研究: QuickCheck