Hibernate的3种继承映射策略:
注意:映射文件名为:父类名.hbm.xml
1,父类和子类使用同一张表:采用 subclass 元素的继承映射
1)因为父类和子类的实例全部保存在同一个表中,因此需要在该表内增加一列,使用该列来区分每行记录到底是哪个类的实例----这个列被称为鉴定者列(discriminator)
2)使用 subclass 来映射子类,使用 class 或 subclass 的 discriminator-value 属性指定鉴定者列的值
注:所有子类定义的字段都不能有非空约束。如果为那些字段添加非空约束,那么父类的实例在那些列其实并没有值,这将引起数据库完整性冲突,导致父类的实例无法保存到数据库中
父类:Article
子类:Topic、Reply
Article.hbm.xml文件:
<?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.jxn.hbm_extends">
<!-- discriminator-value属性:指定鉴定者列的值;如果不写,默认为类的全限定名。-->
<class name="Article" table="article" discriminator-value="Aticle">
<id name="id">
<generator class="native"/>
</id>
<!-- 用于鉴定是什么类型的一个列,必须写在id标签的下面 -->
<discriminator type="string" column="class_"></discriminator>
<property name="title"/>
<property name="content" type="text" length="10000"/>
<property name="postTime" type="timestamp"/>
<!-- 子类:Topic -->
<subclass name="Topic" discriminator-value="Topic">
<property name="type"></property>
</subclass>
<!-- 子类:Reply -->
<subclass name="Reply" discriminator-value="Reply">
<property name="floor"></property>
</subclass>
</class>
</hibernate-mapping>
2,每个类(包括父类)对应一个表:采用 joined-subclass 元素的继承映射
1)子类和父类共有的属性保存在父类表中,子类增加的属性,则保存在子类表中。
2)通过关系数据模型中的外键来描述表之间的继承关系,无须使用鉴别者列,但需要为每个子类使用 key 元素映射共有主键,该主键必须与父类标识属性的列名相同。如果继承树的深度很深,可能查询一个子类实例时,需要跨越多个表,因为子类的数据保存在多个父类中
注:子类增加的属性可以添加非空约束。因为子类的属性和父类的属性没有保存在同一个表中
Article.hbm.xml文件:
<?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.jxn.hbm_extends2">
<!-- 采用每个类一张表的方式,父类也对应表。 -->
<class name="Article" table="article2">
<id name="id">
<generator class="native"/>
</id>
<property name="title"/>
<property name="content" type="text" length="10000"/>
<property name="postTime" type="timestamp"/>
<!-- 子类:Topic -->
<joined-subclass name="Topic" table="topic2">
<key column="id"></key>
<property name="type"></property>
</joined-subclass>
<!-- 子类:Reply -->
<joined-subclass name="Reply" table="reply2">
<key column="id"></key>
<property name="floor"></property>
</joined-subclass>
</class>
</hibernate-mapping>
3,每个子类(不包括父类)对应一张表:采用 union-subclass 元素的继承映射
1)子类实例的数据仅保存在子类表中, 而在父类表中没有任何记录
2)子类表的字段会比父类表的映射字段要多,因为子类表的字段等于父类表的字段和子类增加属性的总和
3)既不需要使用鉴别者列,也无须使用 key 元素来映射共有主键
注:使用 union-subclass 映射策略是不可使用 identity 的主键生成策略, 因为在整个继承结构中,主键值是不能重复的,受此影响, 也不该使用 native 主键生成策略, 因为 native 会根据数据库来选择使用 identity 或 sequence.
Article.hbm.xml文件:
<?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.jxn.hbm_extends3">
<!-- 采用每个子类对应一张表的方式,父类不对应表。abstract默认为false,设为true表示本类不对应表(类可以不是abstract的),这时就会忽略table属性。-->
<class name="Article" abstract="false" table="article3">
<id name="id">
<!-- 主键生成策略不能是identity、sequence、native等自动增长的类型,因为在整个继承结构中,主键值是不能重复的。-->
<generator class="hilo">
<param name="table">hi_value</param>
<param name="column">next_value</param>
<param name="max_lo">100</param>
</generator>
</id>
<property name="title"/>
<property name="content" type="text" length="10000"/>
<property name="postTime" type="timestamp"/>
<!-- 子类:Topic -->
<union-subclass name="Topic" table="topic3">
<property name="type"></property>
</union-subclass>
<!-- 子类:Reply -->
<union-subclass name="Reply" table="reply3">
<property name="floor"></property>
</union-subclass>
</class>
</hibernate-mapping>
Hibernate的3种继承映射策略
最新推荐文章于 2018-10-15 16:37:16 发布