`
langgufu
  • 浏览: 2307442 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Hibernate继承映射多态的详解

阅读更多

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

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

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

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

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

 

People类:

  1. public class People
  2. {
  3. /*父类所拥有的属性*/
  4. private String id;
  5. private String name;
  6. private String sex;
  7. private String age;
  8. private Timestamp birthday;
  9. /*get和set方法*/
  10. }

 

Student类:

  1. public class Student extends People
  2. {
  3. /*学生独有的属性*/
  4. private String cardId;//学号
  5. public String getCardId()
  6. {
  7. return cardId;
  8. }
  9. public void setCardId(String cardId)
  10. {
  11. this.cardId = cardId;
  12. }
  13. }

 

Teacher类:

  1. public class Teacher extends People
  2. {
  3. /*Teacher所独有的属性*/
  4. private int salary;//工资
  5. public int getSalary()
  6. {
  7. return salary;
  8. }
  9. public void setSalary(int salary)
  10. {
  11. this.salary = salary;
  12. }
  13. }

 

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

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

示意图如下:

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

 

配置People.hbm.xml文件:(注意:这里都写在了一个People的配置文件里,也可以分别写在三个配置文件,即Student.hbm.xml、Teacher.hbm.xml里,以下同样可以

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
  3. <hibernate-mapping>
  4. <class name="com.suxiaolei.hibernate.pojos.People" abstract="true">
  5. <id name="id" type="string">
  6. <column name="ID"></column>
  7. <generator class="uuid"></generator>
  8. </id>
  9. <property name="name" column="NAME" type="string"></property>
  10. <property name="sex" column="SEX" type="string"></property>
  11. <property name="age" column="AGE" type="string"></property>
  12. <property name="birthday" column="BIRTHDAY" type="timestamp"></property>
  13. <!--
  14. <union-subclass name="com.suxiaolei.hibernate.pojos.Student" table="STUDENT">
  15. <property name="cardId" column="CARDID" type="string"></property>
  16. </union-subclass>
  17. <union-subclass name="com.suxiaolei.hibernate.pojos.Teacher" table="TEACHER">
  18. <property name="salary" column="SALARY" type="integer"></property>
  19. </union-subclass>
  20. -->
  21. </class>
  22. <!-- 可单独写在Student.hbm.xml里 -->
  23. <union-subclass name="com.suxiaolei.hibernate.pojos.Student"
  24. table="STUDENT" extends="com.suxiaolei.hibernate.pojos.People">
  25. <property name="cardId" column="CARDID" type="string"></property>
  26. </union-subclass>
  27. <!-- 可单独写在Teacher.hbm.xml里 -->
  28. <union-subclass name="com.suxiaolei.hibernate.pojos.Teacher"
  29. table="TEACHER" extends="com.suxiaolei.hibernate.pojos.People">
  30. <property name="salary" column="SALARY" type="integer"></property>
  31. </union-subclass>
  32. </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生成表结构:

  1. drop table if exists STUDENT
  2. drop table if exists TEACHER
  3. create table STUDENT (
  4. ID varchar(255) not null,
  5. NAME varchar(255),
  6. SEX varchar(255),
  7. AGE varchar(255),
  8. BIRTHDAY datetime,
  9. CARDID varchar(255),
  10. primary key (ID)
  11. )
  12. create table TEACHER (
  13. ID varchar(255) not null,
  14. NAME varchar(255),
  15. SEX varchar(255),
  16. AGE varchar(255),
  17. BIRTHDAY datetime,
  18. SALARY integer,
  19. primary key (ID)
  20. )

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

 

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

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

该策略的示意图:

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

 

配置People.hbm.xml:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
  3. <hibernate-mapping>
  4. <class name="com.suxiaolei.hibernate.pojos.People" table="PEOPLE">
  5. <id name="id" type="string">
  6. <column name="ID"></column>
  7. <generator class="uuid"></generator>
  8. </id>
  9. <discriminator column="PEOPLETYPE" type="string"></discriminator>
  10. <property name="name" column="NAME" type="string"></property>
  11. <property name="sex" column="SEX" type="string"></property>
  12. <property name="age" column="AGE" type="string"></property>
  13. <property name="birthday" column="BIRTHDAY" type="timestamp"></property>
  14. <subclass name="com.suxiaolei.hibernate.pojos.Student" discriminator-value="student">
  15. <property name="cardId" column="CARDID" type="string"></property>
  16. </subclass>
  17. <subclass name="com.suxiaolei.hibernate.pojos.Teacher" discriminator-value="teacher">
  18. <property name="salary" column="SALARY" type="string"></property>
  19. </subclass>
  20. </class>
  21. </hibernate-mapping>

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

 

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

  1. drop table if exists PEOPLE
  2. create table PEOPLE (
  3. ID varchar(255) not null,
  4. PEOPLETYPE varchar(255) not null,
  5. NAME varchar(255),
  6. SEX varchar(255),
  7. AGE varchar(255),
  8. BIRTHDAY datetime,
  9. CARDID varchar(255),
  10. SALARY varchar(255),
  11. primary key (ID)
  12. )

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

 

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

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

这种策略的示意图:

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

 

配置People.hbm.xml:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
  3. <hibernate-mapping>
  4. <class name="com.suxiaolei.hibernate.pojos.People" table="PEOPLE">
  5. <id name="id" type="string">
  6. <column name="ID"></column>
  7. <generator class="uuid"></generator>
  8. </id>
  9. <property name="name" column="NAME" type="string"></property>
  10. <property name="sex" column="SEX" type="string"></property>
  11. <property name="age" column="AGE" type="string"></property>
  12. <property name="birthday" column="BIRTHDAY" type="timestamp"></property>
  13. <joined-subclass name="com.suxiaolei.hibernate.pojos.Student" table="STUDENT">
  14. <key column="ID"></key>
  15. <property name="cardId" column="CARDID" type="string"></property>
  16. </joined-subclass>
  17. <joined-subclass name="com.suxiaolei.hibernate.pojos.Teacher" table="TEACHER">
  18. <key column="ID"></key>
  19. <property name="salary" column="SALARY" type="integer"></property>
  20. </joined-subclass>
  21. </class>
  22. </hibernate-mapping>

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

 

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

  1. drop table if exists PEOPLE
  2. drop table if exists STUDENT
  3. drop table if exists TEACHER
  4. create table PEOPLE (
  5. ID varchar(255) not null,
  6. NAME varchar(255),
  7. SEX varchar(255),
  8. AGE varchar(255),
  9. BIRTHDAY datetime,
  10. primary key (ID)
  11. )
  12. create table STUDENT (
  13. ID varchar(255) not null,
  14. CARDID varchar(255),
  15. primary key (ID)
  16. )
  17. create table TEACHER (
  18. ID varchar(255) not null,
  19. SALARY integer,
  20. primary key (ID)
  21. )
  22. alter table STUDENT
  23. add index FK8FFE823BF9D436B1 (ID),
  24. add constraint FK8FFE823BF9D436B1
  25. foreign key (ID)
  26. references PEOPLE (ID)
  27. alter table TEACHER
  28. add index FKAA31CBE2F9D436B1 (ID),
  29. add constraint FKAA31CBE2F9D436B1
  30. foreign key (ID)
  31. references PEOPLE (ID)

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

 

 

在这三种方法中查询速度:第二种方案 > 第一种方案 > 第三种方案。解耦程度:第三种方案 > 第一种方案 > 第二种方案。没有那个绝对好与不好,只有最合适,我们根据需要选择一个最为恰当的即可。由于笔者更注重效率问题,所以个人比较倾向于第二种方案。

分享到:
评论

相关推荐

    Hibernate继承映射(annotation)

    **标题:“Hibernate继承映射(Annotation)详解”** 在Java持久化框架Hibernate中,继承映射是一种关键特性,它允许开发者将对象模型的继承结构映射到数据库的表结构。在传统的面向对象编程中,继承是实现代码复用和...

    hibernate的多态查询

    **标题与描述解析** 标题“hibernate的多态查询”指的是在Hibernate框架中,如何进行涉及...通过阅读提供的文档“Hibernate映射总结.doc”,我们可以深入学习这一主题,进一步探索如何在实践中有效地运用多态查询。

    hibernate的继承映射关系

    ### Hibernate的继承多态映射关系详解 在软件开发领域,特别是使用面向对象编程语言如Java进行开发时,我们经常需要处理复杂的类继承关系。在ORM(Object-Relational Mapping)框架如Hibernate中,如何优雅地将这些...

    hibernate关联映射的作用和常用属性解释

    ### Hibernate关联映射的作用与常用属性详解 #### 关联映射概述 在对象关系映射(Object Relational Mapping,简称ORM)技术中,Hibernate作为Java领域内非常成熟且功能强大的框架之一,它允许开发者将Java类映射...

    hibernate-mapping参数详解

    ### Hibernate Mapping 参数详解 在 Hibernate 中,为了将 Java 对象映射到数据库表,并实现对象关系映射(ORM),开发者需要定义一系列配置属性来指导 Hibernate 如何进行转换。本文将详细解析 `hibernate-mapping...

    精通Hibernate:Java对象持久化技术详解.pdf

    此外,本书还会深入到Hibernate的高级特性,如级联操作、延迟加载、集合映射、多态映射、关联映射(一对一、一对多、多对多)等。这些特性让开发者能够处理复杂的数据结构和业务逻辑。例如,级联操作允许一次操作就...

    精通Hibernate:Java持久化对象技术详解[第二版]

    9. **多态和继承映射**:讲解如何处理类的继承关系,实现多态查询,包括单表继承、联合继承和表格派生。 10. **级联操作与代理**:阐述级联属性的使用,如何实现对象间的联动操作,以及Hibernate的动态代理机制。 ...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part2

     2.4.3 Hibernate映射类型接口  2.4.4 可供扩展的接口  2.5 小结  2.6 思考题 第3章 第一个Hibernate应用  3.1 创建Hibernate的配置文件  3.2 创建持久化类  3.3 创建数据库Schema  3.4 创建对象-关系映射...

    hibernate技术详解------------------

    4. **多态性**:Hibernate支持继承和多态,使得对具有继承关系的实体进行统一管理。 5. **事件监听器**:通过实现特定接口,可以监听和处理实体的生命周期事件,如预加载、加载、保存、更新和删除。 6. **拦截器**:...

    Hibernate Query Language基础使用详解

    在使用HQL时,我们能够查询具有继承、多态和关联关系的数据。 在讲解HQL基础时,我们通常会有一个预先设定的数据库环境。例如,文中提到的`joblog`数据库包含了`student`(学生表)、`course`(课程表)和`sc`(选...

    MyEclipse+Hibernate快速入门中文版

    - 多态关联:能够处理继承关系中的关联问题。 - SQL查询的自定义:允许开发者编写自己的SQL语句进行复杂查询。 Hibernate的核心配置文件为`hibernate.cfg.xml`,在这个文件中可以配置数据库连接信息、使用的数据库...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part4

     2.4.3 Hibernate映射类型接口  2.4.4 可供扩展的接口  2.5 小结  2.6 思考题 第3章 第一个Hibernate应用  3.1 创建Hibernate的配置文件  3.2 创建持久化类  3.3 创建数据库Schema  3.4 创建对象-关系映射...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part3

     2.4.3 Hibernate映射类型接口  2.4.4 可供扩展的接口  2.5 小结  2.6 思考题 第3章 第一个Hibernate应用  3.1 创建Hibernate的配置文件  3.2 创建持久化类  3.3 创建数据库Schema  3.4 创建对象-关系映射...

    Hibernate Query Language

    它与传统的SQL语言非常相似,但更简洁,更重要的是,HQL理解面向对象的概念,如继承、多态、关联、聚合和组合。这使得HQL在处理复杂的对象关系映射时更加灵活和强大。 ### 2. Hibernate查询能力(3.0版本) 自3.0...

    Hibernate annotation 详解

    **Hibernate注解详解** 在Java世界中,Hibernate作为一款强大的对象关系映射(ORM)框架,极大地简化了数据库操作。自Hibernate 3开始,引入了注解(Annotation)支持,使得开发者无需XML配置就能实现对象与数据库...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part1.rar

     2.4.3 Hibernate映射类型接口  2.4.4 可供扩展的接口  2.5 小结  2.6 思考题 第3章 第一个Hibernate应用  3.1 创建Hibernate的配置文件  3.2 创建持久化类  3.3 创建数据库Schema  3.4 创建对象-关系映射...

    hibernate基础 入门/ hibernate basic

    2. **支持常见的面向对象编程概念**:Hibernate支持面向对象编程中常见的概念,如关联(association)、继承(inheritance)、多态(polymorphism)、组合(composition)等。 3. **高性能的对象缓存机制**:...

    hibernate_And_Ibatis.doc

    此外,Hibernate 还支持对象关系的复杂映射,如继承、多态和集合,使得模型更接近面向对象的设计。 **iBATIS** 则更注重 SQL 的控制权,它是一个 SQL Mapping 框架。在 iBATIS 中,SQL 语句由开发者直接编写,然后...

Global site tag (gtag.js) - Google Analytics