上篇我们介绍了关联映射的几种形式,有单向多对一,单向一对多,还有双向一对多。本篇接着介绍有关关联映射的其他几种映射方式,主要有以下几种:

  • 基于外键的单向一对一关联映射
  • 基于主键的单向一对一关联映射
  • 单向多对多关联映射

一、基于外键的单向一对一关联映射

     具有一对一关联的表结构也是很常见的,比如:一个人对应于一张身份证。于是我们的person表会有一个外键关联到 idcard表的主键,只要这个外键列唯一即可保证person到idcard表的关系由多对一变为一对一,也就是说单向的一对一关联映射其实上也就是外键列唯一的多对一的关联映射。例如:

public class Person {
private int id;
private String name;
private IdCard idcard;
//省略get,set方法
}
public class IdCard {
private int id;
private String code;
//省略get,set方法
}
<class name="Person" table="person">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<many-to-one name="idcard" column="idcard_id" unique="true"/>
</class> <class name="IdCard" table="idcard">
<id name="id">
<generator class="native"/>
</id>
<property name="code"/>
</class>

我们可以看到,几乎所有的代码和多对一关联映射都是差不多的,只不过在 many-to-one 元素中指定 unique="true",原来可以有多个具有相同外键值的记录映射到一的一端,现在指定外键值唯一之后,产生了唯一的一对一的关联映射。下面看看我们的测试代码:

//main 方法
Person p1 = new Person();
p1.setName("single"); IdCard idCard = new IdCard();
idCard.setCode("2345"); p1.setIdcard(idCard); session.save(p1);
session.save(idCard);

我们分别创建两端的一个实例对象,然后由person端维护这种关联关系并将数据插入到数据库。看一眼结果:

这就是基于外键的单向一对一关联映射,与多对一的映射的唯一区别就在于,通过指定外键列唯一来让多的一端唯一,从而形成这种一对一的映射关系。

二、基于主键的单向一对一关联映射

     所谓基于主键的映射就是指,其中的一张表的主键值依赖于另一张表的主键值。还是我们的人和身份证模型:

像这种IDCard表完全可以作为属性字段追加到person表的后面的情况(主键重复可覆盖),我们叫这种关联映射为基于主键的一对一关联映射。看看配置文件:

/*person实体类的映射文件的配置*/
<class name="Person" table="person">
<id name="id" column="pId">
<generator class="foreign">
<param name="property">idCard</param>
</generator>
</id>
<property name="name"/>
<one-to-one name="idCard" constrained="true"/>
</class>
/*IDCard实体类的映射文件的配置*/
<class name="IdCard" table="idCard">
<id name="id">
<generator class="native"/>
</id>
<property name="code"/>
</class>

可以看到,主要的变化还是在于实体类person。首先我们指定他的主键不再自增,而是由外键约束到其他表,对应的其他表的类型则是自己实体类的idCard属性对应的表。one-to-one标签则配置了person类中的IdCard属性,便于我们在取数据的时候Hibernate填充数据到该属性中。下面我们添加数据到数据库中,通过查看输出的Sql语句了解Hibernate是如何为我们创建关联的。

Person person = new Person();
person.setName("single"); IdCard idCard = new IdCard();
idCard.setCode("23456789"); person.setIdCard(idCard); session.save(idCard);
session.save(person);

显然,我们对于idcard表的主键指定了native自增,而对于person表的主键并没有指定自增,person表的主键依赖于idcard的主键。我们并不用指定person表的主键值,因为person会根据和自己关联的idcard表的主键来为自己的主键赋值。

三、单向多对多关联映射

     多对多的表关联类型也是非常常见的,例如:

很常见的一个例子,一个学生可以有多个老师,同时一个老师也可以有多个学生,那么这就是很明显的多对多的关联映射。针对这种情况,一般来说数据库的表可以设计如下:

但是这种的表结构设计将会直接导致student表大量冗余,虽然解决了这种多对多的表级关联,但是存在大量冗余。Hibernate中处理这种多对多的关联关系是通过引入另一张表来实现对两个表主键的关联进而关联了两张表。

Student表和teacher表之间的多对多关联完全由connect表进行体现,各自表中数据不再大量冗余,这才是一种比较清晰的表结构设计。下面我们看代码:

public class Student {
private int id;
private String sName;
private Set<Teacher> teachers = new HashSet<Teacher>(0);
//省略get,set方法
}
public class Teacher {
private int id;
private String tName;
//省略get,set方法
}

这是两张表对应的实体类,下面我们主要看映射文件的配置。

/*配置实体类Student*/
<class name="Student" table="student">
<id name="id">
<generator class="native"/>
</id>
<property name="sName"/>
<set name="teachers" table="connect" cascade="save-update">
<key column="stuId"></key>
<many-to-many class="Teacher" column="tId"/>
</set>
</class>
/*配置实体类Teacher*/
<class name="Teacher" table="teacher">
<id name="id">
<generator class="native"/>
</id>
<property name="tName"/>
</class>

Teacher实体类的配置并没有什么特殊需要解释的地方,而对于Student实体类的配置却稍有变化。其中的set标签就负责创建一张新表并负责关联两张表,table属性就是用于连接两张表主键值的表名(connect)。对于用于连接的表,有两个字段,一个是Student表的id,一个是teacher表的id,那么key标签就用于指定Student表id对应connect表中的名称,teacher表的id对应到connect表的名称则由many-to-many标签的column属性指定。下面我们插入多条数据:

显然,通过抽出connect表连关联两张表,对于Student和teacher表的表结构来说是更加简洁清晰的。

至此,有关Hibernate中关联映射的内容已经简单介绍完毕,虽然以后会更多的使用注解来配置这些映射关联,但是都是基于XML的,对于新手来说,学习XML配置关联映射是有助于理解注解配置。总结不到之处,望指出。

初识Hibernate之关联映射(二)的更多相关文章

  1. 初识Hibernate之关联映射(一)

    上篇文章我们对持久化对象进行的学习,了解了它的三种不同的状态并通过它完成对数据库的映射操作.但这都是基于单张表的操作,如果两张或者两张以上的表之间存在某种关联,我们又该如何利用持久化对象进行操作呢?本 ...

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

    上一篇,记录了Hibernate注解----类级别注解以及属性注解详解 ,我们这一节主要讲解的是Hibernate注解----关联映射注解以及课程总结详解. 本节的主要内容: 第3章 关联映射注解 3 ...

  3. Hibernate的关联映射——双向1-N关联

    Hibernate的关联映射--双向1-N关联 对于1-N的关联,Hibernate推荐使用双向关联,而且不要让1的一端控制关联关系,而是用N的一端控制关联关系.双线的1-N关联和N-1关联是两种相同 ...

  4. Hibernate的关联映射——单向1-N关联

    Hibernate的关联映射--单向1-N关联 单向1-N关联的持久化类里需要使用集合属性.因为1的一端需要访问N的一端,而N的一端将以集合(Set)形式表现.从这个意义上来看,1-N(实际上还包括N ...

  5. Hibernate的关联映射——单向1-1关联

    Hibernate的关联映射--单向1-1关联 对于单向的1-1关联关系,需要在持久化类里增加代表关联实体的成员变量,并为该成员变量添加setter方法和getter方法.从持久化类的代码上看,单向1 ...

  6. Hibernate的关联映射——单向N-1关联

    Hibernate的关联映射--单向N-1关联 N-1是非常常见的关联关系,最常见的父子关系也是N-1关联,单向的N-1关联只需从N的一端可以访问1的一端. 为了让两个持久化类能够支持这种关联映射,程 ...

  7. Hibernate之关联映射(一对多和多对一映射,多对多映射)

    ~~~接着之前的Hibernate框架接着学习(上篇面试过后发现真的需要学习以下框架了,不然又被忽悠让去培训.)~~~ 1:Hibernate的关联映射,存在一对多和多对一映射,多对多映射: 1.1: ...

  8. Hibernate的关联映射关系

    一:多对一 <many-to-one 1.name:当前类的属性名(关联映射的类) 2.column:属性多对应的类的对应的表的外键(连接条件) 3.class:属性所对应的类的权限定名 4.n ...

  9. 初识Hibernate之继承映射

         前面的两篇文章中,我们介绍了两张表之间的各种相互关联映射关系,但往往我们也会遇到两张表甚至多张表之间共有着多个相同的字段.例如: 如图,student表和teacher表共同具有id,nam ...

随机推荐

  1. ios 初体验<UILabel控件>

    创建控件: UILabel *label = [[UILabel alloc]init]; //设置控件大小 label.frame = CGRectMake(50,100,300,40);//分别为 ...

  2. ELM极限学习机

    极限学习机(Extreme Learning Machine) ELM,是由黄广斌提出来的求解神经网络算法.ELM最大的特点是对于传统的神经网络,尤其是单隐层前馈神经网络(SLFNs),ELM比传统的 ...

  3. ★不容错过的PPT教程!

    IT工程师必须学会的计算机基础应用之一--PPT! 28项大神级PPT制作技术,学会后让你变成PPT高手哦!更多实用教程,请关注@IT工程师 !

  4. PHP中如何调试?

    比如有个数组: $arr = array('A' => 'bobi','B' => 'hehe'); echo $arr;                //Array   只打印出了变量 ...

  5. MySQL(四)--蠕虫复制、查询

    1 蠕虫复制 蠕虫复制:从已有的数据中去获取数据,然后将数据又进行新增操作,数据成倍增加. 表创建高级操作:从已有创建新表(复制表结构) create table 表名 like 数据库.表名; 蠕虫 ...

  6. java中null的类型匹配

    null作为一个特殊的参数匹配为String对象

  7. Quartz的misfire处理机制分析

    Quartz是一个特性丰富的开源的任务调度开发库,它可以很方便的集成到你的应用程序中.在Quartz中,当一个持久的触发器因为调度器被关闭或者线程池中没有可用的线程而错过了激活时间时,就会发生激活失败 ...

  8. 201521123118《java程序与设计》第8周学习总结

    1. 本周学习总结 1. 以你喜欢的方式(思维导图或其他)归纳总结集合与泛型相关内容. 2. 书面作业 1. List中指定元素的删除(题目4-1) 1.1 实验总结 Scanner sc = new ...

  9. 201521123059 《Java程序设计》第四周学习总结

    1. 本周学习总结 1.1 尝试使用思维导图总结有关继承的知识点. 参考资料: 百度脑图 XMind 1.2 使用常规方法总结其他上课内容. 1.多态性就是相同的形态,不同的行为(不同的定义).多态就 ...

  10. 第2周作业-Java基本语法与类库(20170227-20170304)

    本周学习总结 (1)这周学习认识和熟悉了java的一些类型和变量: (2)学习了java的运算符基本使用方法: (3)了解了如何建立远程仓库和本地仓库,和如何让java代码在临时储存,本地仓库和远程仓 ...