zoukankan      html  css  js  c++  java
  • 【Hibernate框架】三种继承映射

    一、综述

           大家都知道,hibernate作为ORM框架的一个具体实现,最大的一个优点就是是我们的开发更加的能体现出“面向对象”的思想。在面向对象开发中,类与类之间是可以相互继承的(单向继承),而Hibernate中也对这种继承关系提供了自己风格的封装,这就是我们接下来要介绍的Hibernate继承映射的三种策略:

    以下UML图类为例:

    1、每棵类继承树一张表(可以理解为整棵树一张表,表内有所有字段)

    2、每个类一张表(父类、子类、子类各一张表,父表中有公共字段,子表中有个性字段+外键约束)

    3、每个具体类一张表(每个子类一张表,每张表都有自己所有的属性字段)

    二、简介三种继承映射方式的实现:

    实体类也就是我们的PO对象肯定是少不了的,这也是三种方式都必须要有的公共部分了算是:

    Animal.Java:

    1. public class Animal {  
    2.     private int id;  
    3.     private String name;  
    4.     private String sex;  
    5.       
    6.     public int getId(){  
    7.           return id;  
    8.     }  
    9.     public void setId(int id){  
    10.           this.id=id;  
    11.     }  
    12.     public String getName(){  
    13.           return name;  
    14.     }  
    15.     public void setSex(String name){  
    16.           this.name=name;  
    17.     }  
    18.     public String getSex(){  
    19.           return sex;  
    20.     }  
    21.     public void setSex(String sex){  
    22.           this.sex=sex;  
    23.     }  
    24. }  

    Pig.java:

    1. public class Pig extends Animal{  
    2.     private int weight;  
    3.     public int getWeight(){  
    4.           return weight;  
    5.     }  
    6.     public void setWeight(){  
    7.           this.weight=weight;  
    8.     }  
    9. }  

    Bird.java:

    1. public class Bird extends Animal{  
    2.     private int height;  
    3.     public int getHeight(){  
    4.           return height;  
    5.     }  
    6.     public void setHeight(){  
    7.           this.height=height;  
    8.     }  
    9. }  

    三、配置文件分析:

    1、每棵类继承树一张表(可以理解为整棵树一张表,表内有所有字段)

    Extends.hbm.xml

    1. <hibernate-mapping package="com.ssh.hibernate">  
    2.     <class name="Animal">  
    3.         <id name="id">  
    4.             <generator class="native"/>  
    5.         </id>  
    6.         <discriminator column="type" type="string"></discriminator>  
    7.         <property name="name"/>  
    8.         <property name="sex"/>          
    9.         <subclass name="Pig" discriminator-value="Pig">  
    10.             <property name="weight"></property>               
    11.         </subclass>  
    12.         <subclass name="Bird" discriminator-value="Bird">  
    13.             <property name="height"></property>               
    14.         </subclass>          
    15.     </class>  
    16. </hibernate-mapping>  

    配置映射文件时,父类还用<class>标签来定义;添加的区分字段(比如上面表1中的Type字段)需要用<discriminator>标签来定义;用<subclass>标签定义两个子类,与父类“合并”在同一张表里,子类的特有属性用<property>属性定义即可。

    映射文件中的子类<subclass>标签还可以与标签同级,但是要加上属性extends,属性值为父类全路径名称。

    1. <hibernate-mapping package="com.ssh.hibernate">  
    2.     <class name="Animal">  
    3.         <id name="id">  
    4.             <generator class="native"/>  
    5.         </id>  
    6.         <discriminator column="type" type="string"></discriminator>  
    7.         <property name="name"/>  
    8.         <property name="sex"/>         
    9.     </class>  
    10.     <class name="Pig" discriminator-value="Pig" extends="com.ssh.vo.Animal">  
    11.         <property name="weight"></property>               
    12.     </class>  
    13.     <class name="Bird" discriminator-value="Bird" extends="com.ssh.vo.Animal">  
    14.         <property name="height"></property>               
    15.     </class>          
    16.       
    17. </hibernate-mapping>  

    这种映射方式可以把多个类放在一张表中,但是粒度比较粗,有冗余字段;但又是因为多个类的相关记录都存放在一张表中,查询时不用关联,因此效率较高。

    2、每个类一张表(父类、子类、子类各一张表,父表中有公共字段,子表中有个性字段+外键约束)

    Extends.hbm.xml

    1. <hibernate-mapping package="com.ssh.hibernate">  
    2.     <class name="Animal">  
    3.         <id name="id">  
    4.             <generator class="native"/>  
    5.         </id>  
    6.         <property name="name"/>  
    7.         <property name="sex"/>  
    8.         <joined-subclass name="Pig" table="t_pig">  
    9.             <key column="pid" />  
    10.             <property name="weight"/>  
    11.         </joined-subclass>  
    12.         <joined-subclass name="Bird" table="t_bird">  
    13.             <key column="bid"/>  
    14.             <property name="height"/>  
    15.         </joined-subclass>  
    16.     </class>  
    17. </hibernate-mapping>  

           这种方案相对于上层实现(增删改查等操作)不变,因为对象模型并没有改变,只是关系模型改了,只需要修改映射文件即可。缺点:查询时需要关联表,效率差;插入时也要执行多个insert语句,适合继承程度不深的情况。优点:粒度较细,调理清楚,没有冗余

    3、每个具体类一张表(每个子类一张表,每张表都有自己所有的属性字段)

    Extends.hbm.xml

    1. <hibernate-mapping package="com.ssh.hibernate">  
    2.     <class name="Animal" abstract="true">  
    3.         <id name="id">  
    4.             <generator class="uuid"/>  
    5.         </id>  
    6.         <property name="name"/>  
    7.         <property name="sex"/>  
    8.         <union-subclass name="Pig" table="t_pig">  
    9.             <property name="weight"/>  
    10.         </union-subclass>  
    11.         <union-subclass name="Bird" table="t_bird">  
    12.             <property name="height"/>  
    13.         </union-subclass>  
    14.     </class>  
    15. </hibernate-mapping>  

    上面的表有个特点就是,t_pig和t_bird的主键永远都不会相同。因为表面上看起来这是两张表,但实际上存储的都是动物(同一类型),所以还可以看做是一张表。在配置文件中 <union-subclass>标签中不需要key值了,注意Animal的主键生成策略不能是自增(native)了,如果自增的话,pig表中第一条记录id为1,bird表中第一条记录也为1,而它们在实际意义上属于同一类型(可以看做在一张表中),否则可能造成不同子类对应表中的主键相同,所以主键不可一致。配置映射文件时,父类还用<class>标签来定义;用<union-subclass>标签定义两个子类,且每个类对应的表的信息是完全的,包含了所有从父类继承下来的属性。子类的特有属性同样用<property>定义即可。用abstract属性表示父类Animal为抽象类,这样Animal就不会映射成表了。

    四、总结:

           如果系统需要经常进行查操作且子类数量较多,则建议用第一种方案,即每棵生成树映射一张表,这也是最常用的方法,效率较高。如果追求细粒度的设计且子类数量不多,则可以用后两种方案:每个类映射一张表或每个具体类映射一张表。

            假如说我们就是有三张表,分别是T_Animal、T_Pig、T_Bird就是要求我们用sql语句来完成这些级联,大家想过sql语句与hbm.xml配置文件的映射关系吗?其实他就是帮我们做的表union和表join整合思想,大家可以思考一下这个问题。

  • 相关阅读:
    EV3-一种多米诺骨牌搭建机
    UART 通用异步传输器
    用Python进行EV3编程
    vectorized case sum
    Profile your program using GNU gprof
    Usage of the const keyword in C++
    Principles about returning a large data chunk from a function
    [cf1361E]James and the Chase
    [cf1444D]Rectangular Polyline
    [atAGC043B]123 Triangle
  • 原文地址:https://www.cnblogs.com/DoubleEggs/p/6243238.html
Copyright © 2011-2022 走看看