前边我们讲过了如何使用Hibernate来映射多对多的双向的关联关系,即需要在双方的类中都包含一个对方类型的集合属性,然后在各自的hbm.xml文件中使用set节点指定各自的集合属性与第三张中间表格的哪个字段对应即可。今天我们来讲一讲如何映射Java中类与类之间的继承关系。
1.怎么理解这个Java类中的继承关系映射
我们知道,继承是Java的三大特性之一,子类继承父类之后会自动的拥有父类的属性和方法,子类除了拥有父类的属性和方法还拥有自己的属性和方法,那么我们在使用Hibernate将其插入的数据库中的时候如何利用表格维护这种类与类之间的关联关系呢?对于这种类与类之间的继承关系,我们只需要对父类的hbm.xml文件中进行描述就可以了。
2.HIbernate的三种描述类与类之间关联关系映射的方法
① 使用subclass节点描述
在父类的hbm.xml文件中,我们使用subclass节点来描述这种关系。那么在数据库中子类和父类的记录就会共用一张表格,因为共用一张表格,所以我们就不必在考虑关系数据模型中的继承和多态的描述了。
需要注意的是,我们必须要在数据库中子父类共用的表格中额外的添加一个既不在父类中又不在子类中的列来用于区分当前这条数据记录对应的是子类还是父类的记录,这个列就叫做辨别着列。
<class name="父类名称" table="对应的数据库的表名" disciminator-value="数据库表中辨别者类的父类名称" >
<discriminator column="表中辨别者列的名称" type="string"> ---- 配置表格中辨别者列的名称
<subclass name="子类名称" discriminator-value="辨别者列的子类名称">
<property name="子类独有的属性名称" type="string" column="SCHOOL" >
</subclass>
保存时:保存父类或者子类对象时,Hibernate会自动的维护当前对象在数据库中的同一张表中属于父类还是子类,即维护辨别者列。
查询时:当查询父类时,只需查一张表就可以将子类和父类的记录一起查出来,然后选取父类
缺点:
a.在表格中多出了冗余字段,辨别者列
b.子类独有字段不可以添加非空约束,否则父类的数据插不进来(因为这一点使我们不可以容忍的,所以不建议使用这个subclass)
c.当继承的层次较深时,那么在一张表中数据字段也会很多
② joined-class
可以实现每个子类都有一张自己独立的表,子类的实例由父类和子类表共同保存,子类继承的属性在父类中保存,子类独有的属性在子类表中保存。
<joined-subclass name="Student" table="Students" >
<key column="student_id" ></key>
<property name="school" type="string" column="school" ></property>
<joined-subclass>
优缺点
缺点,是插入效率较低,插入一个子类对象时,要插入两张表
优点,不需冗余的辨别者列,可以为子类独有的字段添加非空约束
③使用union-subclass元素映射继承关系
实现将每一个实体对象映射到一个独立的表中,是最符合我们想法的方式。
<unio-subclass name="Student" table="STUDENTS">
<property name="school" column="SCHOOL" type="string" ></proeprty>
</union-subclass>
需要注意的是,此种描述继承关系的union-subclass不可以将生成数据库id的方式设置成identify或者使用hilo自动的使用identify
save:插入性能较好,
select:查子类的记录很好,查父类的记录会将子父类的内容关联起来再一起查询从而将子类的额内容也查询出来,性能偏弱。
缺点:在子类表中存在冗余的字段;跟新父类会很麻烦,需同时跟新子类和父类的表中的数据。
总结:以上三种我们讲过的分别在父类的hbm.xml文件中使用subclass、joined-subclass、union-subclass时,因为第一种subclass中不允许子类独有字段由非空限制,这是我们不可以忍受的,所以我们一般不采用第一种方式,而是采用joined-subclass和union-subclass的方式来映射Java类中继承的关系。
我们在实际项目开发中,一般很少映射继承关系。