在面向对象的程序领域中,类与类之间是有继承关系的,例如Java世界中只需要extends关键字就可以确定这两个类的父子关系,但是在关系数据库的世界中,表与表之间没有任何关键字可以明确指明这两张表的父子关系,表与表是没有继承关系这样的说法的。为了将程序领域中的继承关系反映到数据中,Hibernate为我们提供了3中方案:

 

第一种方案:一个子类对应一张表。

第二种方案:使用一张表表示所有继承体系下的类的属性的并集。

第三种方案:每个子类使用一张表只存储它特有的属性,然后与父类所对应的表以一对一主键关联的方式关联起来。

现在假设有People、Student、Teacher三个类,父类为People,Student与Teacher为People的父类,代码如下:

People类:

public class People
{
/*父类所拥有的属性*/
private String id;
private String name;
private String sex;
private String age;
private Timestamp birthday; /*get和set方法*/
}

  Student类:

public class Student extends People
{
/*学生独有的属性*/
private String cardId;//学号 public String getCardId()
{
return cardId;
} public void setCardId(String cardId)
{
this.cardId = cardId;
}
}

  Teacher类:

public class Teacher extends People
{
/*Teacher所独有的属性*/
private int salary;//工资 public int getSalary()
{
return salary;
} public void setSalary(int salary)
{
this.salary = salary;
}
}

  

第一种方案:一个子类对应一张表

该方案是使继承体系中每一个子类都对应数据库中的一张表。示意图如下:

  每一个子类对应的数据库表都包含了父类的信息,并且包含了自己独有的属性。每个子类对应一张表,而且这个表的信息是完备的,即包含了所有从父类继承下来的属性映射的字段。这种策略是使用<union-subclass>标签来定义子类的。

配置People.hbm.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping>
<class name="com.suxiaolei.hibernate.pojos.People" abstract="true">
<id name="id" type="string">
<column name="id"></column>
<generator class="uuid"></generator>
</id> <property name="name" column="name" type="string"></property>
<property name="sex" column="sex" type="string"></property>
<property name="age" column="age" type="string"></property>
<property name="birthday" column="birthday" type="timestamp"></property> <!--
<union-subclass name="com.suxiaolei.hibernate.pojos.Student" table="student">
<property name="cardId" column="cardId" type="string"></property>
</union-subclass>
<union-subclass name="com.suxiaolei.hibernate.pojos.Teacher" table="teacher">
<property name="salary" column="salary" type="integer"></property>
</union-subclass>
-->
</class>
<union-subclass name="com.suxiaolei.hibernate.pojos.Student"
table="student" extends="com.suxiaolei.hibernate.pojos.People">
<property name="cardId" column="cardId" type="string"></property>
</union-subclass> <union-subclass name="com.suxiaolei.hibernate.pojos.Teacher"
table="teacher" extends="com.suxiaolei.hibernate.pojos.People">
<property name="salary" column="salary" type="integer"></property>
</union-subclass>
</hibernate-mapping>

  

 以上配置是一个子类一张表方案的配置,<union-subclass>标签是用于指示出该hbm文件所表示的类的子类,如People类有两个子类,就需要两个<union-subclass>标签以此类推。<union-subclass>标签的"name"属性用于指定子类的全限定名称,"table"属性用于指定该子类对应的表的名称,"extends"属性用于指定该子类的父类,注意该属性与<union-subclass>标签的位置有关,若 <union-subclass>标签作为<class>标签的子标签,则"extends"属性可以不设置,否则需要明确设置"extends"属性。<class>标签中的"abstract"属性如果值为true则,不会生成表结构。如果值为false则会生成表结构,但是不会插入数据。

根据People.hbm.xml生成表结构:

drop table if exists student
drop table if exists teacher create table student (
id varchar(255) not null,
name varchar(255),
sex varchar(255),
age varchar(255),
birthday datetime,
cardId varchar(255),
primary key (id)
) create table teacher (
id varchar(255) not null,
name varchar(255),
sex varchar(255),
age varchar(255),
birthday datetime,
salary integer,
primary key (id)
)

  

可以看到一个子类对应一张表。

第二种方案:使用一张表表示所有继承体系下的类的属性的并集

  这种策略是使用<subclass>标签来实现的。因为类继承体系下会有许多个子类,要把多个类的信息存放在一张表中,必须有某种机制来区分哪些记录是属于哪个类的。Hibernate中的这种机制就是,在表中添加一个字段,用这个字段的值来进行区分。在表中添加这个标示列使用<discriminator>标签来实现。

该策略的示意图:

将继承体系中的所有类信息表示在同一张表中后,只要是这个类没有的属性会被自动赋上null。

配置People.hbm.xml:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping>
<class name="com.suxiaolei.hibernate.pojos.People" table="people">
<id name="id" type="string">
<column name="id"></column>
<generator class="uuid"></generator>
</id> <discriminator column="peopleType" type="string"></discriminator> <property name="name" column="name" type="string"></property>
<property name="sex" column="sex" type="string"></property>
<property name="age" column="age" type="string"></property>
<property name="birthday" column="birthday" type="timestamp"></property> <subclass name="com.suxiaolei.hibernate.pojos.Student" discriminator-value="student">
<property name="cardId" column="cardId" type="string"></property>
</subclass> <subclass name="com.suxiaolei.hibernate.pojos.Teacher" discriminator-value="teacher">
<property name="salary" column="salary" type="string"></property>
</subclass>
</class>
</hibernate-mapping>

  

<discriminator>标签用于在表中创建一个标识列,其"column"属性指定标识列的列名,"type"指定了标识列的类型。<subclass>标签用于指定该HBM文件代表类的子类,有多少子类就有多少个该标签,其"name"属性指定子类的名称,"discriminator-value"属性指定该子类的数据的标识列的值是什么,其"extends"属性与<union-subclass>的"extends"属性用法一致。

根据People.hbm.xml生成表结构:

drop table if exists people

    create table people (
id varchar(255) not null,
peopleType varchar(255) not null,
name varchar(255),
sex varchar(255),
age varchar(255),
birthday datetime,
cardId varchar(255),
salary varchar(255),
primary key (id)
)

  

可以看到一张表将继承体系下的所有信息都包含了,其中"peopleType"为标识列。

第三种方案:每个子类使用一张表只存储它特有的属性,然后与父类所对应的表以一对一主键关联的方式关联起来。

  这种策略是使用<joined-subclass>标签来定义子类的。父类、子类都对应一张数据库表。在父类对应的数据库表中,它存储了所有记录的公共信息,实际上该父类对应的表会包含所有的记录,包括父类和子类的记录;在子类对应的数据库表中,这个表只定义了子类中所特有的属性映射的字段。子类对应的数据表与父类对应的数据表,通过一对一主键关联的方式关联起来。

这种策略的示意图:

  people表中存储了子类的所有记录,但只记录了他们共有的信息,而他们独有的信息存储在他们对应的表中,一条记录要获得其独有的信息,要通过people记录的主键到其对应的子表中查找主键值一样的记录然后取出它独有的信息。

配置People.hbm.xml:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping>
<class name="com.suxiaolei.hibernate.pojos.People" table="people">
<id name="id" type="string">
<column name="id"></column>
<generator class="uuid"></generator>
</id> <property name="name" column="name" type="string"></property>
<property name="sex" column="sex" type="string"></property>
<property name="age" column="age" type="string"></property>
<property name="birthday" column="birthday" type="timestamp"></property> <joined-subclass name="com.suxiaolei.hibernate.pojos.Student" table="student">
<key column="id"></key>
<property name="cardId" column="cardId" type="string"></property>
</joined-subclass> <joined-subclass name="com.suxiaolei.hibernate.pojos.Teacher" table="teacher">
<key column="id"></key>
<property name="salary" column="salary" type="integer"></property>
</joined-subclass>
</class>
</hibernate-mapping>

  

<joined-subclass>标签需要包含一个key标签,这个标签指定了子类和父类之间是通过哪个字段来关联的。

根据People.hbm.xml生成表结构:

drop table if exists people
drop table if exists student
drop table if exists teacher create table people (
id varchar(255) not null,
name varchar(255),
sex varchar(255),
age varchar(255),
birthday datetime,
primary key (id)
) create table student (
id varchar(255) not null,
cardId varchar(255),
primary key (id)
) create table teacher (
id varchar(255) not null,
salary integer,
primary key (id)
) alter table student
add index FK8FFE823BF9D436B1 (id),
add constraint FK8FFE823BF9D436B1
foreign key (id)
references people (id) alter table teacher
add index FKAA31CBE2F9D436B1 (id),
add constraint FKAA31CBE2F9D436B1
foreign key (id)
references people (id)

  可以看到,父类对应的表保存公有信息,子类对应的表保存独有信息,子类和父类对应的表使用一对一主键关联的方式关联起来。

Hibernate继承映射的更多相关文章

  1. 【JavaEE】Hibernate继承映射,不用多态查询只查父表的方法

    几个月前,我在博问里面发了一个问题:http://q.cnblogs.com/q/64900/,但是一直没有找到好的答案,关闭问题以后才自己解决了,在这里分享一下. 首先我重复一下场景,博问里面举的动 ...

  2. hibernate 继承映射关系( SINGLE_TABLE)

    三种继承映射关系.   1,SINGLE_TABLE   person student  teacher 在一个表中,student和teacher继承自person,通过一个Discriminato ...

  3. Hibernate继承映射(@Inheritance)

    继承映射在 Annotation 中使用 @Inheritance 注解,并且需要使用 strategy 属性指定继承策略,继承策略有 SINGLE_TABLE.TABLE_PER_CLASS 和 J ...

  4. SSH开发实践part3:hibernate继承映射

    0 大家好.上次讲了关于hibernate中双向1-N的映射配置,可以参考:http://www.cnblogs.com/souvenir/p/3784510.html 实际项目中,对象间的关系比较复 ...

  5. web进修之—Hibernate 继承映射(5)

    先看三个类的继承关系,Payment是父类,CashPayment和CreditCardPayment是Payment的子类:   view plaincopy to clipboardprint p ...

  6. Hibernate 继承映射可能会遇到的错误

    问题: 我们在配置hibernate的时候,默认是会配置下面的两个属性的 <property name="hibernate.default_catalog">hibe ...

  7. hibernate 继承映射关系( JOINED)

    一个主表,其他的表每个都有自己的表来装填自己特有的部分,共同的部分就放在主表中.   package com.bjsxt.hibernate; import javax.persistence.Ent ...

  8. hibernate 继承映射关系( TABLE_PER_CLASS)

    Person,Student,Teacher各创建一个表,主键用一个中间表生成.   package com.bjsxt.hibernate; import javax.persistence.Ent ...

  9. Hibernate 继承映射

    @Entity@Inheritance(strategy=InheritanceType.SINGLE_TABLE)@DiscriminatorColumn()public class Animal ...

随机推荐

  1. Codeforces Round #208 (Div. 2)

    A - Dima and Continuous Line 水题:直接模拟: #include<cstdio> #define maxn 1005 using namespace std; ...

  2. Java 编程:如何提高性能?(简单总结篇)

    开发者在编程中除了要有编程规范,还要注意性能,在 Java 编程中有什么提高性能的好办法呢? 本文转自国内 ITOM 行业领军企业 OneAPM Cloud Insight(一款能够优雅监控多种操作系 ...

  3. linux0.11下的中断机制分析

    http://orbt.blog.163.com/     异常就是控制流中的突变,用来响应处理器状态中的某些变化.当处理器检测到有事件发生时,它就会通过一张叫做异常表的跳转表,进行一个间接过程调用, ...

  4. easyui源码翻译1.32--panel(面板)

    前言 昨天发布了表格datagrid的翻译源码 ,easyui的许多插件有依赖关系  比如datagrid 的渲染需要panel.resizable.linkbutton.pagination   今 ...

  5. Altium Designer 特定网络取消 remove loops

    在使用Altium Designer时,在PCB Editor 里面可以设定是否需要Automatically remove Loops,但是这个设置是全局的,在设计时难免会遇到对大部分网络是需要删除 ...

  6. 解决“重新安装vmware-tools”灰色而无法安装的问题

    前几天重装系统,之后虚拟机需要重新装,装好后要使用vmware-tools实现文件共享,却发现虚拟机那里显示为灰色的,无法安装vmware-tools,在共享文件夹那里设置好共享的文件夹猴也没有用,/ ...

  7. web storm使用和配置

    官网:http://www.jetbrains.com/webstorm/ webStorm,File=>setting=>JavaScript-Libraries How WebStor ...

  8. WCF - Consuming WCF Service

    WCF services allow other applications to access or consume them. A WCF service can be consumed by ma ...

  9. .NET(C#)调用webService获取客户端IP地址所属区域(非异步)

    功能描述: 此接口用于获取客户端访问的IP的地址所属的区域(国家,城市等).通过输入IP地址查询国家.城市.所有者等信息.没有注明国家的为中国输入参数:IP地址(自动替换 " ." ...

  10. apache开源项目--ibatis

    iBATIS一词来源于“internet”和“abatis”的组合,是一个由Clinton Begin在2001年发起的开放源代码项目.最初侧重于密码软件的开发,现在是一个基于Java的持久层框架.i ...