1、综述
你们都知道,hibernate做为ORM框架的一个具体实现,最大的一个优势就是是咱们的开发更加的能体现出“面向对象”的思想。在面向对象开发中,类与类之间是能够相互继承的(单向继承),而Hibernate中也对这种继承关系提供了本身风格的封装,这就是咱们接下来要介绍的Hibernate继承映射的三种策略:html
如下UML图类为例:java

一、每棵类继承树一张表(能够理解为整棵树一张表,表内有全部字段)web
二、每一个类一张表(父类、子类、子类各一张表,父表中有公共字段,子表中有个性字段+外键约束)sql
三、每一个具体类一张表(每一个子类一张表,每张表都有本身全部的属性字段)app
2、简介三种继承映射方式的实现:
实体类也就是咱们的PO对象确定是少不了的,这也是三种方式都必需要有的公共部分了算是:框架
Animal.Java:ssh
- public class Animal {
- private int id;
- private String name;
- private String sex;
-
- public int getId(){
- return id;
- }
- public void setId(int id){
- this.id=id;
- }
- public String getName(){
- return name;
- }
- public void setSex(String name){
- this.name=name;
- }
- public String getSex(){
- return sex;
- }
- public void setSex(String sex){
- this.sex=sex;
- }
- }
Pig.java:oop
- public class Pig extends Animal{
- private int weight;
- public int getWeight(){
- return weight;
- }
- public void setWeight(){
- this.weight=weight;
- }
- }
Bird.java:ui
- public class Bird extends Animal{
- private int height;
- public int getHeight(){
- return height;
- }
- public void setHeight(){
- this.height=height;
- }
- }
3、配置文件分析:
一、每棵类继承树一张表(能够理解为整棵树一张表,表内有全部字段)this
Extends.hbm.xml
- <hibernate-mapping package="com.ssh.hibernate">
- <class name="Animal">
- <id name="id">
- <generator class="native"/>
- </id>
- <discriminator column="type" type="string"></discriminator>
- <property name="name"/>
- <property name="sex"/>
- <subclass name="Pig" discriminator-value="Pig">
- <property name="weight"></property>
- </subclass>
- <subclass name="Bird" discriminator-value="Bird">
- <property name="height"></property>
- </subclass>
- </class>
- </hibernate-mapping>
配置映射文件时,父类还用<class>标签来定义;添加的区分字段(好比上面表1中的Type字段)须要用<discriminator>标签来定义;用<subclass>标签订义两个子类,与父类“合并”在同一张表里,子类的特有属性用<property>属性定义便可。
映射文件中的子类<subclass>
标签还能够与标签同级,可是要加上属性extends,属性值为父类全路径名称。
- <hibernate-mapping package="com.ssh.hibernate">
- <class name="Animal">
- <id name="id">
- <generator class="native"/>
- </id>
- <discriminator column="type" type="string"></discriminator>
- <property name="name"/>
- <property name="sex"/>
- </class>
- <class name="Pig" discriminator-value="Pig" extends="com.ssh.vo.Animal">
- <property name="weight"></property>
- </class>
- <class name="Bird" discriminator-value="Bird" extends="com.ssh.vo.Animal">
- <property name="height"></property>
- </class>
-
- </hibernate-mapping>

这种映射方式能够把多个类放在一张表中,可是粒度比较粗,有冗余字段;但又是由于多个类的相关记录都存放在一张表中,查询时不用关联,所以效率较高。
二、每一个类一张表(父类、子类、子类各一张表,父表中有公共字段,子表中有个性字段+外键约束)
Extends.hbm.xml
- <hibernate-mapping package="com.ssh.hibernate">
- <class name="Animal">
- <id name="id">
- <generator class="native"/>
- </id>
- <property name="name"/>
- <property name="sex"/>
- <joined-subclass name="Pig" table="t_pig">
- <key column="pid" />
- <property name="weight"/>
- </joined-subclass>
- <joined-subclass name="Bird" table="t_bird">
- <key column="bid"/>
- <property name="height"/>
- </joined-subclass>
- </class>
- </hibernate-mapping>

这种方案相对于上层实现(增删改查等操做)不变,由于对象模型并无改变,只是关系模型改了,只须要修改映射文件便可。缺点:查询时须要关联表,效率差;插入时也要执行多个insert语句,适合继承程度不深的状况。优势:粒度较细,调理清楚,没有冗余。
三、每一个具体类一张表(每一个子类一张表,每张表都有本身全部的属性字段)
Extends.hbm.xml
- <hibernate-mapping package="com.ssh.hibernate">
- <class name="Animal" abstract="true">
- <id name="id">
- <generator class="uuid"/>
- </id>
- <property name="name"/>
- <property name="sex"/>
- <union-subclass name="Pig" table="t_pig">
- <property name="weight"/>
- </union-subclass>
- <union-subclass name="Bird" table="t_bird">
- <property name="height"/>
- </union-subclass>
- </class>
- </hibernate-mapping>

上面的表有个特色就是,t_pig和t_bird的主键永远都不会相同。由于表面上看起来这是两张表,但实际上存储的都是动物(同一类型),因此还能够看作是一张表。在配置文件中 <union-subclass>标签中不须要key值了,注意Animal的主键生成策略不能是自增(native)了,若是自增的话,pig表中第一条记录id为1,bird表中第一条记录也为1,而它们在实际意义上属于同一类型(能够看作在一张表中),不然可能形成不一样子类对应表中的主键相同,因此主键不可一致。配置映射文件时,父类还用<class>标签来定义;用<union-subclass>标签订义两个子类,且每一个类对应的表的信息是彻底的,包含了全部从父类继承下来的属性。子类的特有属性一样用<property>定义便可。用abstract属性表示父类Animal为抽象类,这样Animal就不会映射成表了。
4、总结:
若是系统须要常常进行查操做且子类数量较多,则建议用第一种方案,即每棵生成树映射一张表,这也是最经常使用的方法,效率较高。若是追求细粒度的设计且子类数量很少,则能够用后两种方案:每一个类映射一张表或每一个具体类映射一张表。
假如说咱们就是有三张表,分别是T_Animal、T_Pig、T_Bird就是要求咱们用sql语句来完成这些级联,你们想过sql语句与hbm.xml配置文件的映射关系吗?其实他就是帮咱们作的表union和表join整合思想,你们能够思考一下这个问题。