在类继承的关系模式下,hibernate的实现继承的方式有三种。简单的总结一下这三种不同的继承映射方式。
就拿上面这张图来说吧。Animal作为一个抽象类出现,Pig有自己的weight属性,Bird也有自己的height属性,他们都有公共的属性name和sex。
整棵类树一张表
这种方式是将这个类树上表示的所有信息都放在一张表中来保存。只是用一个标志性字段将pig和Bird来区分开就行。
具体的映射代码:
<class name="com.bjpowernode.hibernate.Animal" table="t_animal">
<id name="id">
<generator class="native"/>
</id>
<discriminator column="type" type="string"/>
<property name="name"/>
<property name="sex"/>
<subclass name="com.bjpowernode.hibernate.Pig" discriminator-value="P">
<property name="weight"/>
</subclass>
<subclass name="com.bjpowernode.hibernate.Bird" discriminator-value="B">
<property name="height"/>
</subclass>
</class>
这里通过subclass标签来标明子类。discriminator来区分子类,在子类中会通过discriminator-value来区分子类在数据表中所存放的值。
在存储时,此字段不用认为的赋值。很明显,这种方式会造成数据库表中大量冗余字段同时查看时不够方便。
每个类一张表
此种方式是UML图中涉及到的3个种类的分别放在3张表中。Pig和Bird都通过id来与Animal进行关联。
<class name="com.bjpowernode.hibernate.Animal" table="t_animal">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<property name="sex"/>
<joined-subclass name="com.bjpowernode.hibernate.Pig" table="t_pig">
<key column="pig_id"/>
<property name="weight"/>
</joined-subclass>
<joined-subclass name="com.bjpowernode.hibernate.Bird" table="t_bird">
<key column="bid"/>
<property name="height"/>
</joined-subclass>
</class>
这里用了joined-subclass 来标志子类。通过key来进行与animal表连接,作为子表的主键。
此种方式的优点是表中无冗余字段,结构清晰。缺点是:无论是在加载时,还是存储时,继承的层次越多,关联的表就越多,操作就会越麻烦。
每个具体类一张表
这里具体的类是指不是抽象的类。比如Pig是具体的类,Bird是一个具体的类。
<class name="com.bjpowernode.hibernate.Animal" table="t_animal" abstract="true">
<id name="id">
<generator class="assigned"/>
</id>
<property name="name"/>
<property name="sex"/>
<union-subclass name="com.bjpowernode.hibernate.Pig" table="t_pig">
<property name="weight"/>
</union-subclass>
<union-subclass name="com.bjpowernode.hibernate.Bird" table="t_bird">
<property name="height"/>
</union-subclass>
</class>
这里通过union-subclass来标明子类。abstract=“true”不会生成抽象类的表。这种方式的id主键不能设置为自增长。
必须手动分配。如果继承的子类过多,就会很麻烦。
以上三种方式就是继承映射中涉及到的几种表结构方式。三种方式各自有各自的优缺点。通常还是采用第一种方式更加方便。