双向关联一对一映射详解(1)
一、双向主键关联
双向的主键关联其实是单向一对一主键关联的一种特殊情况,只不过要在关联对象的两端的映射文件中都要进行<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;
- }
- //idCard
- private 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 写入测试
- 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 加载测试
- 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);
- }
- }
运行上面的测试方法,在控制台打印的相关内容如下:
结语
双向关联一对一映射详解(1)相关推荐
- 双向关联一对一映射详解(2)
二.双向外键关联 双向的外键关联可以理解为外键关联的一种特殊情况,这种特殊主要是由于它是一种双向的对应关系,在前篇文章中提到如果想要在一张表中添加一个外键字段的话可以使用<many-to-one ...
- 【Hibernate步步为营】--双向关联一对一映射具体解释(一)
一对一的映射在对象模型中是常常见到的,为了将对象模型转换为关系模型就必须在映射文件里进行配置,上篇文章讨论了一对一映射的单向关联的情况,重点是<one-to-one>标签的使用,须要在映射 ...
- Hibernate对象关系映射详解之一对多关系映射
Hibernate对象关系映射详解之"一对多"关系映射 之前学习Hibernate框架的时候,对这七大关系映射一直是云里雾里的,虽然可以仿照写出代码,但是不能独立编写出来.鉴于工作 ...
- FluentNHibernate之基本映射详解
最近在做项目的时候用到了NHibernate,使用它并不困难,但是很麻烦.如果我的数据库有几百张表如果想要一个个的映射岂不是很麻烦,所以这种情况下使用NHibernate就会很笨重,虽然这个ORM框架 ...
- Mybatis映射详解
Mybatis映射详解 在最近的工作中,碰到一个比较复杂的返回结果,发现简单映射已经解决不了这个问题了,只好去求助百度,学习mybatis复杂映射应该怎么写,将学习笔记结合工作碰到的问题写下本文,供自 ...
- elasticsearch最全详细使用教程:入门、索引管理、映射详解、索引别名、分词器、文档管理、路由、搜索详解
一.快速入门 1. 查看集群的健康状况 http://localhost:9200/_cat http://localhost:9200/_cat/health?v 说明:v是用来要求在结果中返回表头 ...
- Elastricsearch 索引操作详解(快速入门、索引管理、映射详解、索引别名)
一.快速入门 1. 查看集群的健康状况 http://localhost:9200/_cat http://localhost:9200/_cat/health?v 说明:v是用来要求在结果中返回表头 ...
- ElasticSearch最全详细使用教程:入门、索引管理、映射详解、索引别名、分词器、文档管理、路由、搜索详解...
墨墨导读:之前我们分享了ElasticSearch最全详细使用教程:入门.索引管理.映射详解,本文详细介绍ElasticSearch的索引别名.分词器.文档管理.路由.搜索详解. 一.索引别名 1. ...
- ElasticSearch最全详细使用教程:入门、索引管理、映射详解
墨墨导读:本文介绍了ElasticSearch的必备知识:从入门.索引管理到映射详解. 一.快速入门 1. 查看集群的健康状况http://localhost:9200/_cat http://loc ...
最新文章
- 黑马程序员—易混淆的知识
- RSA体系 c++/java相互进行加签验签--转
- WPF 自动选择dll,以SQLite为例
- 关于An association from the tablea refers to an unmapped classB
- 深入解析:你听说过Oracle数据库的更新重启动吗?
- 组内Linq培训记录
- 一个简单的完全信息动态博弈的解答
- SQL2008安装教程
- Python基于周立功ZCANPRO开发刷写脚本
- matconvnet编译
- Mybatis快速入门及遇到的问题(不支持发行版本)(黑马程序员Javaweb)
- (白光LED显色性)计算白光LED的显色指数(CRI)数据异常,色质指数CQS来替代
- 汉语语法与人工智能---数据结构+汉语语法
- html如何加页脚,html-如何将页脚扩展到页面底部?
- Android中连接MQTT服务器实现发布一个消息推送给订阅者(附代码下载)
- 2020胡润80后白手起家富豪榜公布,掌门教育张翼强势登榜
- 螺栓检测项目 螺栓检测报告河南
- html css样式绘制向下或者向上箭头
- 元芳,你怎么看?元芳是谁?
- 【历史上的今天】2 月 19 日:Hacker News 上线;Adob​​e Photoshop 诞生;DVD 退出历史舞台
热门文章
- 查看文件md5_软件推荐丨go-fastdfs——高性能、高可靠分布式文件系统
- linux fork脚本,在Shell脚本中调用另一个脚本的三种方式讲解
- mysql安装之后怎么进入_MySQL常规练习 .MySQL安装成功后的进入方式
- node mysql查询回调_nodejs 数据库查询回调问题
- OpenShift Security (1) - 红帽多集群安全管理 RHACS 的主要功能和技术架构
- (十)DeepFaceLab:预包装的DIY深度伪造替代品
- 通过数据扩充来扩展数据集
- SpecFlow的力量
- 在.NET中实现观察者模式(3种技术)
- 微软开源数据处理引擎 Trill,每天可分析万亿次事件