在面向对象的程序领域中,类与类之间是有继承关系的,例如Java世界中只需要extends关键字就可以确定这两个类的父子关系,但是在关系数据库的世界中,表与表之间没有任何关键字可以明确指明这两张表的父子关系,表与表是没有继承关系这样的说法的。为了将程序领域中的继承关系反映到数据中,Hibernate为我们提供了3中方案:
第一种方案:一个子类对应一张表。
第二种方案:使用一张表表示所有继承体系下的类的属性的并集。
第三种方案:每个子类使用一张表只存储它特有的属性,然后与父类所对应的表以一对一主键关联的方式关联起来。
现在假设有People、Student、Teacher三个类,父类为People,Student与Teacher为People的父类,代码如下:
People类:
publicclass People
{
/*父类所拥有的属性*/
private String id;
private String name;
private String sex;
private String age;
private Timestamp birthday;
/*get和set方法*/
}
Student类:
publicclass Student extends People
{
/*学生独有的属性*/
private String cardId;//学号
public String getCardId()
{
return cardId;
}
publicvoid setCardId(String cardId)
{
this.cardId = cardId;
}
}
Teacher类:
publicclass Teacher extends People
{
/*Teacher所独有的属性*/
privateint salary;//工资
publicint getSalary()
{
return salary;
}
publicvoid 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生成表结构:
droptableifexists student
droptableifexists teacher
createtable student (
id varchar(255) notnull,
name varchar(255),
sex varchar(255),
age varchar(255),
birthday datetime,
cardId varchar(255),
primarykey (id)
)
createtable teacher (
id varchar(255) notnull,
name varchar(255),
sex varchar(255),
age varchar(255),
birthday datetime,
salary integer,
primarykey (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生成表结构:
droptableifexists people
createtable people (
id varchar(255) notnull,
peopleType varchar(255) notnull,
name varchar(255),
sex varchar(255),
age varchar(255),
birthday datetime,
cardId varchar(255),
salary varchar(255),
primarykey (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生成表结构:
droptableifexists people
droptableifexists student
droptableifexists teacher
createtable people (
id varchar(255) notnull,
name varchar(255),
sex varchar(255),
age varchar(255),
birthday datetime,
primarykey (id)
)
createtable student (
id varchar(255) notnull,
cardId varchar(255),
primarykey (id)
)
createtable teacher (
id varchar(255) notnull,
salary integer,
primarykey (id)
)
altertable student
addindex FK8FFE823BF9D436B1 (id),
addconstraint FK8FFE823BF9D436B1
foreignkey (id)
references people (id)
altertable teacher
addindex FKAA31CBE2F9D436B1 (id),
addconstraint FKAA31CBE2F9D436B1
foreignkey (id)
references people (id)
可以看到,父类对应的表保存公有信息,子类对应的表保存独有信息,子类和父类对应的表使用一对一主键关联的方式关联起来。
第一种方案:一个子类对应一张表。
第二种方案:使用一张表表示所有继承体系下的类的属性的并集。
第三种方案:每个子类使用一张表只存储它特有的属性,然后与父类所对应的表以一对一主键关联的方式关联起来。
现在假设有People、Student、Teacher三个类,父类为People,Student与Teacher为People的父类,代码如下:
People类:
publicclass People
{
/*父类所拥有的属性*/
private String id;
private String name;
private String sex;
private String age;
private Timestamp birthday;
/*get和set方法*/
}
Student类:
publicclass Student extends People
{
/*学生独有的属性*/
private String cardId;//学号
public String getCardId()
{
return cardId;
}
publicvoid setCardId(String cardId)
{
this.cardId = cardId;
}
}
Teacher类:
publicclass Teacher extends People
{
/*Teacher所独有的属性*/
privateint salary;//工资
publicint getSalary()
{
return salary;
}
publicvoid 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生成表结构:
droptableifexists student
droptableifexists teacher
createtable student (
id varchar(255) notnull,
name varchar(255),
sex varchar(255),
age varchar(255),
birthday datetime,
cardId varchar(255),
primarykey (id)
)
createtable teacher (
id varchar(255) notnull,
name varchar(255),
sex varchar(255),
age varchar(255),
birthday datetime,
salary integer,
primarykey (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生成表结构:
droptableifexists people
createtable people (
id varchar(255) notnull,
peopleType varchar(255) notnull,
name varchar(255),
sex varchar(255),
age varchar(255),
birthday datetime,
cardId varchar(255),
salary varchar(255),
primarykey (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生成表结构:
droptableifexists people
droptableifexists student
droptableifexists teacher
createtable people (
id varchar(255) notnull,
name varchar(255),
sex varchar(255),
age varchar(255),
birthday datetime,
primarykey (id)
)
createtable student (
id varchar(255) notnull,
cardId varchar(255),
primarykey (id)
)
createtable teacher (
id varchar(255) notnull,
salary integer,
primarykey (id)
)
altertable student
addindex FK8FFE823BF9D436B1 (id),
addconstraint FK8FFE823BF9D436B1
foreignkey (id)
references people (id)
altertable teacher
addindex FKAA31CBE2F9D436B1 (id),
addconstraint FKAA31CBE2F9D436B1
foreignkey (id)
references people (id)
可以看到,父类对应的表保存公有信息,子类对应的表保存独有信息,子类和父类对应的表使用一对一主键关联的方式关联起来。
相关推荐
本主题将深入探讨"Hibernate继承映射+C3P0代码"的相关知识点。 首先,让我们理解Hibernate的继承映射。在Java中,我们可以创建一个基类,然后派生出多个子类,这种设计模式在数据库中也可以被映射出来。Hibernate...
Hibernate继承映射是将Java类的继承关系映射到数据库表的一种策略,使得对象模型的复杂性能够平滑地转化为关系数据库模型。本篇将详细介绍Hibernate继承映射的第一种策略——每棵类继承树对应一张表,即单一表继承...
《Hibernate继承映射详解》 Hibernate,作为Java领域中的一款著名对象关系映射(ORM)框架,极大地简化了数据库操作。在实际项目中,我们常常会遇到类的继承关系,而Hibernate提供了强大的支持来处理这种继承关系的...
**标题:“Hibernate继承映射(Annotation)详解”** 在Java持久化框架Hibernate中,继承映射是一种关键特性,它允许开发者将对象模型的继承结构映射到数据库的表结构。在传统的面向对象编程中,继承是实现代码复用和...
《Hibernate继承映射详解》 在Java开发中,对象关系映射(ORM)框架如Hibernate大大简化了数据库操作。Hibernate不仅提供了对基本数据类型的映射,还支持复杂的数据结构,如继承关系的映射。本篇文章将深入探讨...
本篇文章将详细探讨Hibernate继承映射的策略,特别是“每个具体类一张表”(Table Per Concrete Class)的映射方式。 在面向对象编程中,继承是常见的代码复用手段,但在关系型数据库中,这种概念并不直接对应。...
本文将详细探讨“Hibernate继承映射的第一种策略:每个类对应一张表”的概念、实现方式以及其优缺点。 首先,我们需要理解Hibernate继承映射的基本策略。在面向对象编程中,类继承是常见的代码复用手段,但在数据库...
针对hibernate的继承映射部分做了几个测试的例子,更加直观的阐述了继承映射的几种方式以及对应的表结构方式,文件被分割成3部分 http://download.csdn.net/source/259075 http://download.csdn.net/source/259072 ...
本篇主要探讨的是Hibernate中的继承映射策略,特别是“每个子类一张表”(Table per subclass)的方式。这种方式也被称为单表继承或多表继承,是Hibernate支持的四种继承映射策略之一。了解并熟练掌握这种映射模式...
### 用Hibernate映射继承关系 #### 14.1 继承关系树的每个具体类对应一个表 在Hibernate中映射继承关系时,一种常见的策略是将继承关系树的每个具体类映射到单独的数据库表中。这种方法称为**表/类映射**(Table/...
本篇文章主要探讨的是Hibernate的继承映射策略,特别是“每个类分层结构一张表”(Table per Concrete Class)的方式。这种映射策略是Hibernate提供的多种继承映射方案之一,适用于处理复杂的对象模型。 首先,我们...
在Java世界中,ORM(对象关系映射)框架如Hibernate极大地简化了数据库操作。本教程主要探讨的是Hibernate中的“继承映射...学习并实践这些例子,有助于巩固对Hibernate继承映射的理解,并提升在实际项目中的应用能力。