Hibernate(七)——继承映射

通过前面几篇文章,介绍了关联映射的一些概念。在实际应用中,关联映射用到的最多。除此之外,还会较多的用到本文讲到的继承映射。

实现继承映射,主要有三种策略:单表继承、具体表继承和类表继承。

单表继承——每棵继承树使用一个表;

具体表继承——每一个类分别使用一个表;

类表继承——每个具体类分别使用一个表。


看下图集成结构:Pig和Bird都属于Animal,并且Pig和Bird都分别有自己特有的属性。分下使用三种继承映射对它进行实现。


Hibernate(七)——继承映射_第1张图片


继承映射无论采用三种策略中的哪一种,实体类均是一样的。子类继承父类Animal,并各自拥有各自的属性。这里不做过多介绍。


1、每棵继承树使用一张表的映射


此种映射方式,在数据库中,只生成一个表。此外,表中会多一个鉴别字段:

映射方式:

<?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.lzq.hibernate">
	<class name="Animal" table="t_animal" lazy="true">
		<id name="id">
			<generator class="native" />
		</id>
		<!-- 此处为在配置中加的鉴别字段,用于对Pig和Bird做出区分-->
		<discriminator column="type" type="string"/>
		<property name="name" />
		<property name="sex" />
		<!-- 当discriminator的值为P时,为Pig,特有属性为weight-->
		<subclass name="Pig" discriminator-value="P">
			<property name="weight" />
		</subclass>
		<!-- 当discriminator的值为P时,为Pig,特有属性为height-->
		<subclass name="Bird" discriminator-value="B">
			<property name="height" />
		</subclass>
	</class>
</hibernate-mapping>


显然,该种策略,对少量数据的查询有着得天独厚的优势,只有一张表,节约查询时间,简单易行。而缺点就是存在冗余字段,而且面对大数据量,就会显得有些吃力。


2、每个类一张表使用一张表的映射


该种映射方式,映射的结果,有几个类,就会生成几个表。因此,在此例中会生成三个表:

Hibernate(七)——继承映射_第2张图片

映射方式:

<?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.lzq.hibernate">
	<class name="Animal" table="t_animal">
		<id name="id">
			<generator class="native" />
		</id>
		<property name="name" />
		<property name="sex" />
		<!--
              每个类使用一张表:每个<joined-subclass>标签生成一张表,
             <joined-subclass>标签下的<key>标签映射成主键,<property>映射成字段
        -->
		<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>


该种映射方式不存在数据冗余,但是每次查询,最少查询两张表。


3、每个具体类一张表的映射


本例中存在两个具体类,即会映射成两张表:

Hibernate(七)——继承映射_第3张图片


映射方式:


<?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.lzq.hibernate">
	<!-- 需要在class标签上设置abstract为true,不然会生成Animal表 -->
	<class name="Animal" table="t_animal" abstract="true">
		<!-- 主键生成策略必须采用手动赋值的方式-->
		<id name="id">
			<generator class="assigned" />
		</id>
		<property name="name" />
		<property name="sex" />
		<!-- 
             每个具体类一张表:只有每个<union-subclass>标签会生成一张表有意义的表,
            <property>标签映射成特有字段
        -->
		<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>

每个具体类一张表映射,不能采用自增的方式生成主键。原因就是增加一个Pig,然后在增加一个Bird的时候,可能出现重复主键。


总结一下:

每个继承树一张表优点是:查询速度快,效率高;缺点是:存在大量冗余,而且在查询的数据特别大时,不适合采用该种方式。

每个类一张表优点是:层次清楚,无冗余;缺点是:类的层次多,并且有一个类就需要有一个表,导致会产生很多表。而且,查询时关联的表太多,影响查询速度。

每个具体类一张表优点是:层次清楚,无冗余;缺点是:使用自增主键方式会产生重复逐渐。


总之,最好的方式就是根据具体情况,酌情选择。

你可能感兴趣的:(数据库,Hibernate,框架)