Hibernate征途(六)之数量和关系映射

来源:互联网 发布:a 寻路算法 java 编辑:程序博客网 时间:2024/04/28 16:01

    本来如果和关系模型一样,只需要一对一、一对多、多对多映射就够了,但是前面《Hibernate征途(四)之映射 序》中说到,对象模型中关联是有方向的,所以对一对多而言,就会产生一对多还是多对一的问题,同时一种映射会产生两种方向,简单罗列一下如下:

  • 多对一映射
  • 一对一单向主键映射
  • 一对一双向主键映射
  • 一对一单向唯一外键关联
  • 一对一双向唯一外键关联
  • 一对多单向关联
  • 一对多双向关联
  • 多对多单向关联
  • 多对多双向关联

    鉴于前面提到的理由,我不会对每个映射细粒度分析,以下我们从类属性、映射文件、数据库表来解释一下这些映射。

方向

    上面罗列的映射都提到方向的问题,在前面的博客中提到对象模型的关联是有方向的,也对这种方向做了简单的阐述,下面我们用班级Classes和学生Student两个类来说明一下方向:

    无方向

    Student

public class Student {private int id;private String name;        //省略getter和setter……}

    Classes

public class Classes {private int id;private String name;        // 省略getter和setter……}
    很明显,这种情况下,知道Student和Classes哪个对象都不知道另外一个对象的存在。

    单向双向

    Student

    public class Student {        private int id;        private String name;        private Classes classes;        //省略getter和setter……}
    Classes

public class Classes {private int id;private String name;        //省略getter和setter……}
    在这种情况下,知道一个Student对象,就可以知道它多对应的Claases对象,反之则不行,这为单向;同样,如果在Classes中也添加对Student的引用,就是双向关联,此时二者可以相互知道对方的存在。

    综合上面所说,所谓的方向性,就是是否有另外一个对象的引用,当然因为还需要Hibernate的映射文件中添加属性的映射;同时这种方向性并不会影响到数据的存储结构。

数量

    抽离上面说到的方向,文章最开始提到的多种映射可以分为:一对一映射、多对一映射、一对多映射和多对多映射。如果从关系模型上看,这种数量对应的存储之间的关联,如果从对象模型上看,我认为它的意思是一种对象包含或引用另外一种对象的数量关系,这种关系最直接的体现在属性和映射上面,同时多对一还是一对多基于的角度不同,例如以一对多双向映射中的Student和Classes为例:

    从Student的角度看,有关Classes的属性为:

private Classes classes;
    映射文件中关于classes的为:
    <many-to-one name="classes"  column="classesid" />
    从Classes的角度看,有关student的属性为:
private Set students;

    映射文件中关于students的为:

    <set name="students"  inverse="true">        <key column="classesid" />        <one-to-many class="com.tgb.hibernate.Student" />    </set>

    说到这里,再说一下映射文件与表中列的关系,最开始的博客就说到,property和id标签都会产生对应的数据列,那么映射文件中关于数量的标签会不会产生列?这取决于对应方式。

    综上来看,“数量”说的是引用的方式(一还是多)及对应的数量映射标签。

综合

    上面抽离出数量和方向,接下来把最上面罗列的映射大体分析一下。

    一对一

    如果是一对一的映射,会有两种方式:

  • 主键:在关系模型中,两张表使用其中一张表的主键,保证一一对应。
  • 外键:在关系模型中,体现的是一张表使用另外一张表的外键,不过要求此外键唯一,实际上这是个特殊的一对多关联,使用<many-to-one name="idCard" unique="true" />。

    多对一和一对多

    一对多和多对一映射的原理是相同的,都是在多的一端加入一个外键关联,二者之间的区别是在于维护的关系不同,仍然以Student和Classes为例

  • 在多对一中,添加的维护是在Student一端:
<hibernate-mapping ><class name="com.tgb.hibernate.Student"  table="t_student"><id name="id"><generator class="native" /></id><property name="name" /><many-to-one name="classes" column="classesid" /></class></hibernate-mapping>

    它们是多指向一的关系,通过维护这个关系,在加载多的一端时,可以把一的一端一起加载。

  • 在一对多中,添加的维护是在Classes一端:
<hibernate-mapping ><class name="com.tgb.hibernate.Classes"  table="t_classes"><id name="id"><generator class="native" /></id><property name="name" /><set name="students"><key column="classesid" /><one-to-many class="com.tgb.hibernate.Student" /></set></class></hibernate-mapping>
    它是一指向多的关系,维护二者的关系,在加载一的一端的时候可以把多的一端加载上来。

    多对多

    在关系模型中,多对多的关系会使用中间表维护,映射到对象模型中一样。以角色Role和用户User为例:

    Role

<hibernate-mapping ><class name="com.tgb.hibernate.Role" table="t_role" ><id name="id"><generator class="native" /></id><property name="name" /><set name="users"  table="t_user_role"><key column="role_id" /><many-to-many class="com.tgb.hibernate.User" column="user_id"/></set></class></hibernate-mapping>

    User

<hibernate-mapping ><class name="com.tgb.hibernate.User" table="t_user" ><id name="id"><generator class="native" /></id><property name="name" /><set name="roles"  table="t_user_role"><key column="user_id" /><many-to-many class="com.tgb.hibernate.Role" column="role_id" /></set></class></hibernate-mapping>

    在多对多中,把关系表与其中一张实体表理解成多对一的关系,更有助于理解。

总结

    这篇博客没有针对每种映射说明,只是抽象出这些数量和方向型映射的共性,希望可以给大家一些理解的思路。下篇博客介绍组合主键映射和集合映射。

原创粉丝点击