前几篇博文中讲到了常用的几种关联映射。其实Hibernate中还有一种“省劲儿”的映射,那就是——“继承映射”。
学了这么多的关系映射了,继承映射,从字面上也能了解到猜到几分。没错,继承映射就是为继承树而设置的一种映射方案。
继承映射的实现有三种策略:
- 单表继承。每棵类继承树使用一个表
- 类表继承。每个子类生成一个表。
- 具体表继承。每个类生成一个表。
我们还是用实例来说明一下,直接上图吧:
![](https://box.kancloud.cn/2016-02-18_56c53c111ef89.jpg)
Pig和Bird都继承自Animal,它们都有id,name,sex,但是Pig主要看weight,而Bird主要看height,此时如果把这些数据存入到数据库中,可以有3种方案,正好对应3种策略。
①. 只生成一个table,对应的继承映射策略是“单表继承”。如图:
![](https://box.kancloud.cn/2016-02-18_56c53c112f66f.jpg)
②. 每个类生成一个table,对应的继承策略是“类表继承”。如图:
![](https://box.kancloud.cn/2016-02-18_56c53c113feb0.jpg)
③. 生成3张表,对应的策略是“具体表继承”。如图:
![](https://box.kancloud.cn/2016-02-18_56c53c114d90c.jpg)
相信大家更愿意看代码,那就用代码说一下吧:
~~~
public class Animals {
private int id;
private String name;
private boolean sex;
//此处省略get,set方法
}
public class Bird extends Animals {
private int height;
//此处省略get,set方法
}
public class Pig extends Animals {
private int weight;
//此处省略get,set方法
}
~~~
第一种对应的映射文件:使用discriminator和subclass标签
~~~
<?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">
<class name="Animals" table="t_animals" lazy="false">
<id name="id">
<generator class="native"/>
</id>
<discriminator column="type" type="string"></discriminator>
<property name="name"/>
<property name="sex"></property>
<subclass name="Pig" discriminator-value="P">
<property name="weight"></property>
</subclass>
<subclass name="Bird" discriminator-value="B">
<property name="height"></property>
</subclass>
</class>
</hibernate-mapping>
~~~
discriminator,英文解释是“辨别器”。它是用于设置辨别数据的字段,放在id下面,同时使用subclass来配置不同的类,设置discriminator-value,来辨别不同的数据。
第二种映射文件:使用union-subclass标签
~~~
<?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">
<class name="Animals" table="t_animals" abstract="true">
<id name="id">
<!-- 不能使用native,因为自增会出现两个表一样的id -->
<generator class="assigned"/>
</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>
~~~
第三种映射文件:使用joined-subclass标签
~~~
<?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">
<class name="Animals" table="t_animals" lazy="false">
<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>
~~~
以上三种策略,各有优缺点:
- 单表继承。查询速度最快,效率高,但是存在冗余字段。
- 类表继承。层次清楚,无冗余;但是如果使用自增主键方式会产生重复主键。需要使用手动分配主键。
- 具体表继承。层次最明了,这是优点,也是缺点,而且数据操作效率不高。
- 前言
- Struts 简单小结
- 深入浅出了解Struts的处理流程(有图有真相)
- struts标签+jstl标签之国际化实例
- 一口一口吃掉Hibernate(二)——别被世俗蒙蔽了双眼:Hibernate中Session之get和load方法的真正区别
- 一口一口吃掉Hibernate(一)——使用SchemaExport生成数据表
- 一口一口吃掉Hibernate(三)——Hibernate给表和字段设置前后缀及分隔符
- 一口一口吃掉Hibernate(四)——多对一单向关联映射
- 一口一口吃掉Hibernate(五)——一对多单向关联映射
- 一口一口吃掉Hibernate(六)——多对多关联映射
- 一口一口吃掉Hibernate(七)——继承映射
- 一口一口吃掉Hibernate(八)——Hibernate中inverse的用法
- 一览Spring全貌
- 包办婚姻的Spring IoC
- 3幅图让你了解Spring AOP
- Spring Aop实例之xml配置
- Spring Aop实例之AspectJ注解配置