千山万水之Hibernate(五)——关联映射(一对一)

知道了多对一关联映射的映射原理,我们再来看一对一关联的情况,一对一分映射有两种实现方案:

一对一主键关联映射

对于其中关联的情况我们又各分为单向、双向两种,而对于一对一,Hibernate采用one-to-one标签进行标识。

原理分析

我们拿人(Person)与身份证件(IdCard)为一对一关联对象的示例,他们的实体关系图为:

采取第一种方案,则Person对应数据库表与IdCard对应数据库表中的主键是一一对应的,不需要添加多余的字段来表示外键。Person关联映射文件中的配置为:

<?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>
    <class name="com.tgb.hibernate.Person" table="t_person">
        <id name="id">
            <!-- 主键策略foreign -->
            <generator class="foreign">
                <!-- property指关联对象 -->
                <param name="property">idCard</param>
            </generator>
        </id>
        <property name="name" />
        <one-to-one name="idCard" constrained="true" />
    </class>
</hibernate-mapping>

注:one-to-one标签中的 constrained=”true”表示当前主键同时也是一个外键,参照IdCard中的主键。

操作示例

1.调用session的Load方法,得出Person对象的级联班级对象IdCard

public void testLoad(){
    Session session = null;
    Transaction tx = null;
    try{
        session = HibernateUtils.getSession();
        tx = session.beginTransaction();

        Person person = (Person)session.load(Person.class, 1);
        System.out.println("person.name = " + person.getName());
        System.out.println("person.idCard.cardNo = " + person.getIdCard().getCardNo());

        session.save(person);

        tx.commit();
    }catch(Exception e){
        e.printStackTrace();
        if(tx != null){
            tx.rollback();
        }
    }finally{
        HibernateUtils.closeSession(session);
    }
}

与上篇文章介绍的类似,通过one-to-one标签的作用,我们查询Person对象的同时,级联查询除了IdCard对象

2.默认级联保存Idcard机制

public void testSave(){
    Session session = null;
    Transaction tx = null;
    try{
        session = HibernateUtils.getSession();
        tx = session.beginTransaction();

        IdCard idCard = new IdCard();
        idCard.setCardNo("11111111111");

        Person person = new Person();
        person.setName("张三");
        person.setIdCard(idCard);

        session.save(person);

        tx.commit();
    }catch(Exception e){
        e.printStackTrace();
        if(tx != null){
            tx.rollback();
        }
    }finally{
        HibernateUtils.closeSession(session);
    }
}

上篇文章中我们提到过,在引用有Transient对象的Persistent状态的对象进行保存时,会出现异常,但在一对一主键关联映射上不会出现此种情况。也就是说,一对一默认带有cascade属性。对于一对一主键关联映射,双向关联的配置即是在IdCard端加入one-to-one标签即可,此标签仅影响加载,不影响存储。

综合来看将来如果改为多对一则不可修改,灵活性较差、扩展性不好。

一对一外键关联映射

我们可将一对一的情况看作是多对一情况的一种极端体现,我们可以采用many-to-one标签配合unique属性来给其相对应的表上添加外键字段,这种方式可解决使用主键关联映射的弊端。相关映射文件如下:

<?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>
    <class name="com.tgb.hibernate.Person" table="t_person">
        <id name="id">
            <generator class="native" />
        </id>
        <property name="name" />
        <many-to-one name="idCard" unique="true"></many-to-one>
    </class>
</hibernate-mapping>

有关相应的操作,可参照前一篇文章的多对一下示例。

总结

我们可以看到一对一主键关联到一对一外键关联的转变可以看作是另一种角度下看待问题,通过这样的思想,一些原本要求苛刻的情况我们同样可以通过另一种方式来处理,达到相同的效果,并且实现将来变更的灵活应对。

时间: 2024-10-07 00:55:32

千山万水之Hibernate(五)——关联映射(一对一)的相关文章

千山万水之Hibernate(四)——关联映射(多对一)

在上一篇文章(<千山万水之Hibernate(三)--基本映射 >)中,我们介绍了怎样通过Hibernate进行最基本的单实体映射以及Hibernate设计的一些基本原理,本篇文章将介绍关联映射中的多对一映射是如何实现的. 原理分析 我们拿学生和班级为示例,学生属于某一个班级,而且多个学生是有可能属于同一个班级的,相应的实体关系图为: Class的映射文件向上一篇我们介绍到的基本映射文件那样编写便可以,而对于Student实体,我们需要从Student中得出对应班级,而Student与Clas

千山万水之Hibernate(七)——关联映射(多对多)

一直认为通过写SQL语句来处理多对多的情况比较复杂,对表关系必须是理解的非常清楚,在学习了Hibernate中的多对多处理后,想想其实多对多也没什么,只不过多了一张表,如果说多了一张表感觉复杂了,Hibernate中我们完全不用去理会他,直接去操作关联实体就可以了,从这点上看,Hibernate为我们做了很多事,确实功不可没. 在有了Hibernate这个帮手后,今天一起看看我们在Hibernate的基础上进行一些操作. 原理分析 我们拿学生和课程为例子来分析,所谓的多对多关系可以这样理解:一个

千山万水之Hibernate(六)——关联映射(一对多)

学习Hibernate的过程中,映射是比较重要的一部分,再说其中哪一种映射比较重要(或可以说是比较常用)呢?那一定很多人会想到一对多关联映射.之所以这样说,是因为在生活中很多这样的实例:班级-学生.企业-员工.文件夹-文件.试卷-题目等.至于生活中为什么会遇到这样大量一对多的情况,似乎是哲学方面的事情了,当然大家可以继续思考,而我们今天主要讨论Hibernate中的一对多. 原理分析 我们仍然拿班级.学生之间的关系做例子:一个班级包含多个学生.相应的实体关系图为: 单向关联 由图可知,由于单向的

千山万水之Hibernate(八)——继承映射

类之间的关系,我们可以分为四种:关联.依赖.继承.实现.而我们所说的实体类之间的关系往往会想到两种:关联和继承,其他两种为什么会不是很常用?首先类之间的依赖是一种比较弱的关系,在代码上可以理解为在一个类的方法的参数上或方法内部对另一个类有引用或调用,引用类或调用类不属于原始类的变量类型,实体类之间一般不存在方法,也就谈不上依赖了.实现描述的是类与接口的关系,一般接口用于定义方法,也就是相当于定义出一些规范,不进行实现. 在前面几篇文章中,我们了解和学习了如何使用Hibernate进行实体类之间的

千山万水之Hibernate(八)——Component映射

Component映射体现一种封装复用的思想,我们知道数据域模型的设计一般是粗粒度的,而对象模型的设计我们往往遵循细粒度.单一职责.抽象复用的原则,但到了对象模型与数据模型相互转换.对应的时候,我们就需要考虑来怎样实现来同时满足双方的基本设计理念.Hibernate中就提供相关的实现. 原理分析 对象模型: User类与Employee类存有很多相同的属性,为了更好的可维护性与灵活性,进行抽象.复用得出了Contact类,Contact类是不需要映射到数据库中表的,有了这样的需求,Hiberna

千山万水之Hibernate(十三)——锁

锁主要是为了解决数据的并发访问问题.悲观锁,通常是由数据库机制实现,在整个过程中把数据锁住(查询时),只要事务不释放,任何用户都不能查看或修改.Hibernate中对悲观锁进行了封装. 测试示例 悲观锁 同时执行两个测试方法,同时采用悲观锁方式访问同一条数据记录. 1.建立测试实体 package com.tgb.hibernate; /** * 库存实体 * @author Forrest * */ public class Inventory { //物料编码 private String

千山万水之Hibernate(二)——Hibernate的三态

Session是Hibernate向应用程序提供的操纵数据库的最主要的接口,我们可以通过Session来操作Java对象,完成对应数据库的操作.从根据Session管理的角度来看需要持久化的对象可以分为三种状态:Transient.Persistent.Detached.它们之间的关系如图所示: Transient(瞬时):没有被Session所管理(即不处于Session的缓存中)的持久化对象所处的状态.刚用new语句创建,还没有被持久化. Persistent(持久化):已经被持久化,已经加

Hibernate注解----关联映射注解以及课程总结详解----图片版本

上一篇,记录了Hibernate注解----类级别注解以及属性注解详解 ,我们这一节主要讲解的是Hibernate注解----关联映射注解以及课程总结详解. 本节的主要内容: 第3章 关联映射注解 3-1 本章简介 3-2 实体之间的关系 3-3 一对一单向外键关联(一) 3-4 一对一单向外键关联(二) 3-5 一对一双向外键关联 3-6 一对一单向外键联合主键 3-7 多对一单向外键关联(一) 3-8 多对一单向外键关联(二) 3-9 一对多单向外键关联 3-9 一对多双向外键关联 3-10

hibernate 之 关联映射的基于外键的双向一对一关联

1. 人和身份证是一个一对一的关系,他们的表结构为: 2. 类结构:Person.java public class Person { private int id; private String name; private int age; private IdCard idCard; public Person() { } public Person(String name, int age) { super(); this.name = name; this.age = age; } pu