类之间有一种关系叫做继承关系,这种关系描述为子类继承了父类所有的属性和方法。
继承关系在hibernate框架中主要有三种表现方式
- 1.单表继承,每棵类继承树使用一张表
- 2.具体表继承; 每个子类一个表
- 3.类表继承。每个具体类一个表(有一些限制)
1.单表继承
父类(Animal)和子类(Pig、Bird)只生成一张表,该表中包括了父类和子类的所有属性,
因为类继承树肯定是对应多个类,要把多个类的信息存放在一张表中,必须有某种机制来区分哪些记录是属于哪个类的。这种机制就是,在表中添加一个字段,用这个字段的值来进行区分。
关于鉴别值(Type)在存储的时候hibernate会自动存储,在加载的时候会根据鉴别值取得相关的对象
t_animal
Id | Name | Sex | Weight | Height | Type |
1 | 小猪 | True | 200 | | P |
2 | 小鸟 | False | | 50 | B |
Hibernate中的映射文件:
<?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="Animal" table="t_animal"> <id name="id"> <generator class="native"/> </id> <discriminator column="type" type="string"/> <property name="name"/> <property name="sex"/> <subclass name="Pig" discriminator-value="P"> <property name="weight"/> </subclass> <subclass name="Bird" discriminator-value="B"> <property name="height"/> </subclass> </class> </hibernate-mapping> |
请注意红色的关键字subclass(控制子类生成方式)和鉴别字段和鉴别值
优点:查询效率高,符合数据库设计粗粒度(推荐)
缺点:存在冗余字段,有些字段是子类不具有的属性。
2.每个类一张表
父类(Animal)和子类(Pig、Bird)均生成一张表,其中父类表中存放公共的属性,子类表中分别存放各自的属性字段,子表的主键均来自主表。如下表所示:
Hibernate中的映射文件
<?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="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"/> <property name="weight"/> </joined-subclass> <joined-subclass name="Bird" table="t_bird"> <key column="bid"/> <property name="height"/> </joined-subclass> </class> </hibernate-mapping> |
请注意使用红色的关键字joined-subclass(控制子类生成方式)
优点:数据结构清晰,没有冗余
缺点:类的继承层次比较多的话,造成生成的表也比较多,增删改查效率低下
3.每个具体类一张表
父类Animal不会生成表,每个子类(Pig、Bird)生成一张表。子类除具有父类的所有属性字段外,还有自己的属性字段,如下图所示:
t_pig
Id | Name | Sex | Weight |
1 | 小猪 | True | 200 |
t_bird
Id | Name | Sex | Height |
2 | 小鸟 | False | 50 |
hibernate中的映射文件
<?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="Animal" table="t_animal" abstract="true"> <id name="id"> <generator class=""/> </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> |
请注意红色的关键字abstract(控制父类表不再生成) 和 union-subclass (控制子类生成方式)
优点:数据结构清晰
缺点:两个子表的主键不能重复,不能使用数据库的自增方式生成主键。
总结:
1. 通过总结这三种方式的优缺点发现,使用继承树生成一张表的方式似乎更符合数据库粗粒度设计的原则。当然数据量非常大的话也可以考虑每个类生成一张表的成方式
2.程序的对象模型没有发生变化,变化的是关系模型。
这就是hibernate的好处,想改变关系模型,只需要改变映射文件即可。