SSH——Hibernate继承关系映射详解(配置+实例+总结)



     继承、泛化、关联是面向对象常见关系,在实际编程中,不少出现它们的身影。Hibernate作为JDBC的良好包装者,对于这些常见关系也通过配置文件得以灵活实现。

在Hibernate应用中,实体间继承关系的应用主要有三种策略:
1、单表继承:n个继承实体共用1张表
2、具体表继承:每个子类分别创建1张表
3、类表继承:每个具体类分别创建一张表

其中以1、2方式使用居多。下面先来看看三个策略的具体使用,通过对比,总结相互的异同点。

一、单表继承:
小猪、鸟继承与动物类:

1、创建3个实体类 (此处省略get set方法),

public class Animal {
//公有属性
 private int id;
 private String name;
 private String sex;
 }
 
public class Bird extends Animal{
 private int height;
}
public class Pig extends Animal{
 private int weight;
}

2、编写配置文件,只创建一张t_animal表,加入鉴别字段,判断动物类型:

<hibernate-mapping package="com.bjpowernode.hibernate">
 <class name="Animal" table="t_animal">
  <id name="id">
   <generator class="native"/>
  </id> 
  <!-- 加入鉴别字段  type  猪p 鸟b -->
  <discriminator column="type" type="string" ></discriminator> 
  <property name="name"/>
  <property name="sex"/> 
  
  <subclass name="Pig" discriminator-value="P">
   <property name="weight"></property>
  </subclass>
  <subclass name="Bird" discriminator-value="B">
   <property name="height"></property>
  </subclass>
 </class>
3、导出表结构,CRUD测试结果(此处省略部分代码)  
 //插入:
   Pig pig=new Pig();
   pig.setName("little");
   pig.setSex("male");
   pig.setWeight(130);
   //注意将对象纳入session管理
   session.save(pig);
   
   
   Bird bird=new Bird();
   bird.setName("bird");
   bird.setSex("famale");
   bird.setHeight(178);
   //注意将对象纳入session管理
   session.save(bird); 
   
   //加载
   Pig pig=(Pig)session.load(Pig.class, 1);
   System.out.println(pig.getName()); 
   
      以上两个测试方法,结果分别为 , t_animal表中分别新增pig 和bird两条记录,加载显示pig名称

      通过例子可以看出,单表继承的特点就是不管继承关系存在多少类,配置文件就1个,创建的表就1张。它通过加入鉴别字段,判断子类类型,插入数据库。这样做的好处就在于表单一,好维护,crud时不用关联过多表获取数据。但缺点就在于数据比较冗余。如上,鸟没有weight属性,则该字段在数据库中为空,同理,小猪也没有height属性,则该字段在数据库中也为空。

二、具体表继承:
 同样继承关系,我们来看看具体表继承是如何创建表的。
1、3个实体类同上 
2、编写配置文件:

<hibernate-mapping package="com.bjpowernode.hibernate">
 <class name="Animal" table="t_animal">
  <id name="id">
   <generator class="native"/>
  </id>
  <property name="name"/>
  <property name="sex"/> 
  
  <joined-subclass name="Pig" table="t_pig">
   <key column="pid"></key>
   <property name="weight"></property>
  </joined-subclass>
  
  <joined-subclass name="Bird" table="t_bird">
   <key column="bid"></key>
   <property name="height"></property>
  </joined-subclass>
 </class>
</hibernate-mapping>

3、导出表结构,CRUD测试结果
 导出的表结构如下:


 测试类不变,同样可生成数据,不过是t_pig,t_bird,t_animal中分别生成1,,1,2条数据。
从创建的表关系可以看出,具体表继承是在继承关系中有多少个类,创建多少张表。父表包含多个从表公有属性字段,从表中通过逐渐id与父表id关联维护关系。这种策略就避免了单表继承数据冗余的缺点。但就是表相对较多,查询时可能需要关联多张表操作,操作数据比较繁琐。
三、类表继承:
1、3个实体类同上
2、编写配置文件:

<class name="Animal" table="t_animal">
  <id name="id">
   <generator class="assigned"/>
  </id> 
  <discriminator column="type" type="string"/> 
  <property name="name"/>
  <property name="sex"/> 
  
  <union-subclass name="Pig" table="t_pig">
<!--  木有key外键了<key column="pid"></key> -->
   <property name="weight"></property>
  </union-subclass>
  
  <union-subclass name="Bird" table="t_bird">
<!--    <key column="bid"></key> -->
   <property name="height"></property>
  </union-subclass>
 </class>

3、导出表结构,CRUD测试结果


       同样三张表,但插入数据时,只对子表也就是t_pig,t_bird插入,而t_animal并未改动数据。
       所以在这个策略中,利用抽象-具体的概念,某个子类是具体类,创建相应表。而父类抽象,t_animal 表不负责实际存值,只是一张抽象的表。笔者目前还没发现这张抽象表起何作用,并且可以通过abstract=“true”,将其省略。第三种方式,虽然也类似于子类各一张表,但个表中数据是完整的,父类虽然包含了公有属性,但对应父表并不起数据存储作用,每个公有属性都分别由子表自己存储。对于继承关系,笔者认为并未起到太大作用,只是配置文件用了<union-subclass>标签关联。



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值