【Hibernate】继承映射

来源:互联网 发布:什么是可逆矩阵 编辑:程序博客网 时间:2024/05/14 06:39
【前言】
    不知道大家是否还记得UML中的四种关系?自己回想了一下,还是没有忘记的,分别是继承、实现、依赖和关联。
    怎么突然会想到这样一个问题?是因为在学习完Hibernate关联映射之后,紧接着又来了一个继承映射。关联和继承,都属于四种关系之一,所以,本篇博客就先提了个问题,下面就开始继承映射的学习。
【概述】
    继承是面向对象语言的三大重要特性之一,它实现了代码的复用。而Hibernate对于此特性在对应的对象模型配置文件中也作出了各种配置,可将其与关系模型的关系分为三种情况:
    1. 每棵类继承树一张表
    2. 每个类一张表
    3. 每个具体类一张表
    下面我们就逐一看看,它们各自生成的关系模型有着哪些不同?以下通过动物类和猪类、鸟类三者间的关系为实例,利用不同继承映射的方法去建表。
    三个类之间的关系如下所示:
【一、继承映射之每棵类继承树一张表】
    1. 含义:此方法的意思是不管父类拥有多少个子类,都只会根据父类去生成一张表,而各个子类中有单独的字段,都添加到父类生成的那张表中。
    2. 设计:从图上看,这张表至少包含的字段有:id,name,sex,weight和height。但因为子类不止一个,如果没有一个标识字段,那么就无法从数据表中看到记录是属于哪个子类的。所以,此张表的结构与数据应该如下:
t_animal:
IdNameSexWeightHeightType1小猪猪True200 P2小鸟鸟False 100B

    根据图建立对应的对象模型,也就是所说的实体类,本篇博客中实体类代码就不再展示了。
    3. 配置及注释:
<?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 package="com.bjpowernode.hibernate">    <!-- 新建表,名为t_animal。不采用延迟加载 -->    <class name="Animal" table="t_animal" lazy="false">        <!-- 该表的主键字段id,生成策略为native -->        <id name="id">            <generator class="native"/>        </id>        <!-- 在父类使用discrimination标签,用来指定标识字段的列名和类型 -->        <discriminator column="type" type="string"/>        <!-- 父类的name属性 -->        <property name="name"/>        <!-- 父类的sex属性 -->        <property name="sex"/>        <!-- 子类Pig,标识字段值为P -->        <subclass name="Pig" discriminator-value="P">            <!--  子类Pig的weight属性  -->            <property name="weight"/>        </subclass>        <!-- 子类Bird,标识字段值为B -->        <subclass name="Bird" discriminator-value="B">            <!--  子类Bird的height属性  -->            <property name="height"/>        </subclass>    </class></hibernate-mapping>  
     4. 结果:
    5. 小结:
    此种方法的结果就是数据库中只有一张根据父类建立的表,而不同子类的子属性也全都写入到这张表中,增加一个区分字段即可。
    6. 优缺点:
    (1)表中引入的区分子类的字段,也就是包括了描述其他字段的字段。
    (2)如果某个子类的某个属性不能为空,那么在数据库一级不能设置该字段not null(非空)
    (3)维护起来方便,只需要修改一个表
    (4)灵活性差,表中冗余字段会随着子类的增多而越来越多
    【二、继承映射之每个类一张表】
    1. 含义:此种方法的意思是每个类都建立一张单独的表。
    2. 设计:从图上看,共包含三个类,则应该建立三张表:t_animal、t_pig和t_bird。三张表的结果和数据如下所示:

    
     3. 配置即注释:

<?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 package="com.bjpowernode.hibernate"><!-- 建立表t-animal -->    <class name="Animal" table="t_animal">    <!-- 该表的主键字段id,生成策略为native -->        <id name="id">            <generator class="native"/>        </id>        <!-- t_animal的属性字段name和sex -->        <property name="name"/>        <property name="sex"/>        <!-- joined-subclass生成策略,新建表t_pig -->        <joined-subclass name="Pig" table="t_pig">        <!-- 指定了pig子类和animal父类之间是通过pid字段关联 -->            <key column="pid"/>            <!-- pig子类的子属性,weight -->            <property name="weight"/>        </joined-subclass>        <!-- joined-subclass生成策略,新建表t_bird -->        <joined-subclass name="Bird" table="t_bird">        <!-- 指定了bird子类和animal父类之间是通过bid字段关联 -->            <key column="bid"/>            <!-- bird子类的子属性,height -->            <property name="height"/>        </joined-subclass>    </class></hibernate-mapping> 
4. 结果:

    5. 小结:

    此种方法的结果是数据库中每个类都对应生成一张表,父类拥有自己的属性字段,子类加上与父类关联的主键字段和自己的子属性。
    6. 优缺点:
    (1)这种设计方式完全符合关系模型的设计原则,且不存在冗余
    (2)维护起来比较方便,对每个类的修改只需要修改其所对应的表,灵活性很好,完全是参照对象继承的方式进行配置
    (3)对于父类的查询需要使用左外链接,对于子类查询需要使用内链接
    (4)对于子类的持久话至少要处理两个表
    【三、继承映射之每个具体类一张表】
    1. 含义:此种方法的意思是每个子类都建立一张单独的表,而父类不生成对应的表
    2. 设计:从图上看,共包含两个具体类,则应该建立两张表:t_pig和t_bird。两张表的结果和数据如下所示:

    
     3. 配置即注释:

<?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 package="com.bjpowernode.hibernate"><!-- 定义该表的abstract属性为true,则不会生成具体的表 -->    <class name="Animal" table="t_animal" abstract="true">        <id name="id">        <!-- 让应用程序在save()之前为对象分配一个标示符。这是 <generator>元素没有指定时的默认生成策略。 -->            <generator class="assigned"/>        </id>        <property name="name"/>        <property name="sex"/>        <!-- union-subclass生成策略,t_pig表的信息是完整的,也就是包含id,name,sex和weight四个字段 -->        <union-subclass name="Pig" table="t_pig">        <!-- 子属性字段weight -->            <property name="weight"/>        </union-subclass>        <!-- union-subclass生成策略,t_bird表的信息是完整的,也就是包含id,name,sex和height四个字段 -->        <union-subclass name="Bird" table="t_bird">        <!-- 子属性字段height -->            <property name="height"/>        </union-subclass>    </class></hibernate-mapping>  
4. 结果:

    5. 小结:

    此种方法的结果是数据库中每个子类都对应生成一张表,每个子类的属性是各自的子属性加上父类的共同属性。
    6. 优缺点:
     (1) 这种设计方式符合关系模型的设计原则,但有表中存在重复字段的问题。
     (2) 如果需要对基类进行修改,则需要对基类以及该类的子类所对应的所有表都进行修改         
     (3) 对于子类的查询只需要访问单独的表,对父类查询需要检索所有的表,对于单个对象持久话操作只需要处理一个表
    【总结】
    对于这三种继承映射方法,目前还没有在项目中遇到过,所以三者之间如何选择?通常选择什么?都没有概念。不过总体思想应该仍旧是:没有最好,选择合适的就好。也期待在项目中见到对它们的应用。

1 0