实体的继承
实体类支持类继承、多态关联和多态查询。实体类可以继承非实体类,非实体也也可以继承实体类。实体类可以是抽象类也可以是具体类。
roster实例应用演示了实体的继承,相关描述参见:“roster应用中的实体继承” page 620.
抽象实体
通过使用@Entity注解,一个抽象类可以被声明为一个实体。抽象实体类似体实体,但是抽象不能被实例化。
可以像查询具体实体一样查询抽象实体。如果抽象实体是查询对象,查询操作就执行在该抽象实体的所有具体实体上:
@Entity
public abstract class Employee {
@Id
protected Integer employeeId;
...
}
@Entity
public class FullTimeEmployee extends Employee {
protected Integer salary;
...
}
@Entity
public class PartTimeEmployee extends Employee {
protected Float hourlyWage;
}
带映射超类(Mapped Superclasses)
实体可能继承自超类,这些超类包括持久化状态和映射信息,但是并不是实体。这就是说,超类并没有使用@Entity注解休息,也没有被Java持久化提供商映射(到数据库)。当你有多个实体的通用状态及映射信息时,通常会使用这种超类。(TODO:此处最好举个例子说明。译注:如更新时间、更新者等字段)
带映射超类,可通过注解javax.persistence.MappedSuperclass指定:
@MappedSuperclass
public class Employee {
@Id
protected Integer employeeId;
...
}
@Entity
public class FullTimeEmployee extends Employee {
protected Integer salary;
...
}
@Entity
public class PartTimeEmployee extends Employee {
protected Float hourlyWage;
...
}
带映射超类不能够被查询,也不可以用于EntityManager及Query操作。你只能使用其实体类的子类。带映射超类也不可以用于指定实体关系。带映射超类可以是抽象的也可以是具体的。
在底层数据库中,带映射超类没有任何关联的表。继承自带映射超类的实体定义(实体到)表的映射。例如在代码示例中,底层表是FULLTIMEEMPLOYEE和PARTTIMEEMPLOYEE,但是却没有表EMPLOYEE。
非实体超类
实体可以有非实体超类,而这些超类也可以是抽象类或具体类。非实体超类的状态是非持久化的,而且实体类继承自非实体超类的状态也是非持久化的。非实体超类不可以用于EntityManager及Query操作。非实体超类上的任何映射或者关系注解都会被忽略。
实体继承的映射策略
You can configure how the Java Persistence provider maps inherited entities to the underlying datastore by decorating the root class of the hierarchy with the annotation javax.persistence.Inheritance. The following mapping strategies are used to map the entity data to the underlying database:
你可以使用注解javax.persistence.Inheritance修饰继承树的根类,以配置如何将实体映射到底层数据库。可使用下列映射策略将实体映射到底层数据库:
■ 每套实体类对应一个表
■ 每个具体实体类对应一个表
■ 一种“连接”策略,这种策略下,子类特有字段或特性被映射到单独的表,而不是用于保存父类通用字段或特性的表。
这种策略通过设定@Inheritance注解的strategy元素来配置,可选的配置项定义在枚举类型javax.persistence.InheritanceType中:
public enum InheritanceType { SINGLE_TABLE,
JOINED, TABLE_PER_CLASS
};
如果继承树上的根类没有指定@Inheritance注解,则会使用默认的策略: InheritanceType.SINGLE_TABLE。
一套实体类对应一张表的策略
这种策略下,即使用默认值InheritanceType.SINGLE_TABLE时,层级中所有类都映射到数据库中的一个表中。这个表有一个区分(discriminator)列,该列的值标识了一行记录所代表的实例是哪个子类。
区分列的元素如表 32–2所示,可以在类层级的根类上,使用注解javax.persistence.DiscriminatorColumn 指定。
表 32–2 @DiscriminatorColumn的元素
类型 名称 描述
String Name 用来作为区分列的实际列的名称。默认值是DTYPE这个元素是可选的。
DiscriminatorType discriminatorType 区分列的类型,默认值是DiscriminatorType.STRING。这个元素是可选的。
String columnDefinition 用来创建区分列的SQL语句。默认由持久化供应商生
成,而且这个是根据具体实现不同而不同。
这个元素是可选的
String Length 当类型是DiscriminatorType.STRING时,此字段为列的长度,对于非STRING类型,此字段会被忽略。
其默认值是31,这个元素是可选的。
The javax.persistence.DiscriminatorTyp枚举类型是用来设定数据库中的区分列类型的。@DiscriminatorColumn注解的discriminatorType元素使用其作为参数值,DiscriminatorTyp的定义如下:
public enum DiscriminatorType { STRING,
CHAR, INTEGER
};
如果实体层级的类实体没有指定@DiscriminatorColumn,而又需要一个区分列时,持久化供应商会假定默认的区分列名为DTYPE列的类型为DiscriminatorType.STRING。
可以用javax.persistence.DiscriminatorValue注解来为每层实体设置区分列的值。你可以用@DiscriminatorValue只修饰具体实体。
如果指定了区分列,但是未设定@DiscriminatorValue的值,持久化供应商会提供一个默认的,跟具体实现有关的值。如果@DiscriminatorColumn的discriminatorType元素是DiscriminatorType.STRING,那默认的值就是实体名称。
这个策略良好地支持了实体层级间的多态关系。但是这种策略需要子类的属性(state)可为空。
每个具体类一张表的策略
这种策略下,即指定为InheritanceType.TABLE_PER_CLASS时,每个具体映射到一个数据库中的单独的一个表。类中所有字段和特性,包括继承的字段和特性,都映射到该类自己的表上的字段中。
这种策略对多态关系支持的不好,在需要涵盖整个实体层级的查询查询,通常需要使用SQL的UNION语句来合并查询,或者分别查询每个子类。
This strategy provides poor support for polymorphic relationships and usually requires either SQL UNION queries or separate SQL queries for each subclass for queries that cover the entire entity class hierarchy.
对这种策略的支持是可选的,而且持久化供应商可能会不支持。GlassFish服务器中,默认的JPA供应商就不支持这种策略。
连接子类策略
这种策略,即指定为InheritanceType.JOINED时,类层级的根类映射到一张表,然后其其每个子类分别映射到一个表,其只包括子类特有的字段。这就是说,子类的表不包括继承来的字段或特性。子类表也有一个(或一些)列来标识它的主键,子类表的主键也是父类表的主键的外键。
这种策略提供了对多态关系的良好支持,但在实例化实体子类时,需要至少一次做一次连接操作。这可能会导致处理扩展类层级时存在性能问题。类似的,查询整个实体类层级需要对子表做连接操作,也会导致性能降低。
一些JPA供应商,包括GlassFish服务器中默认的供应商,在使用连接子类策略时,需要一个区分列来标识根实体。如果你的应用没有使用自动建表,请确认数据库表正确配置了默认区分列,或者使用@DiscriminatorColumn注解映射到你数据库的schema中。更多关于区分列的信息,参见“每套类层级一个表策略” on page 597.
分享到:
相关推荐
《Java EE 6 教程》是Oracle公司于2010年发布的一部详尽指导书籍,旨在帮助开发者深入理解和掌握Java Platform, Enterprise Edition(Java EE)平台的应用开发技术。Java EE 6作为企业级应用开发的标准框架,提供了...
《Java EE 5 Tutorial》是Java企业版5(Java Platform, Enterprise Edition 5)的一份官方教程,旨在帮助开发者深入理解和掌握Java EE平台的核心技术。这份文档详细介绍了如何使用Java EE 5进行分布式应用程序的开发...
《Java EE 6 Tutorial: Basic Concepts, Fourth Edition》是一本面向新手及中级Java开发者的指南书籍,旨在帮助他们深入理解Java平台企业版6(Java EE 6)的各项特性与技术。本书由Oracle公司Java EE 6文档团队成员...
Java EE 6(Java Platform, Enterprise Edition 6)是Java技术在企业级开发中的一个里程碑,它为构建可扩展、高性能、分布式的企业级应用程序提供了全面的框架和规范。本教程由Sun Microsystems(后被Oracle收购)...
The Java EE 5 Tutorial为学习Java EE 5的经典教材!一直由sun公司维护,不过为全英文版.
Java EE 6 APIs in the Java Platform, Standard Edition 6.0 31 GlassFish Server Tools 34 Chapter 2: Using the Tutorial Examples 37 Required Software 37 Starting and Stopping the GlassFish Server ...
根据给定的文件信息,我们将深入探讨与Java EE 7教程相关的关键知识点,这将包括对Java EE平台的理解、其核心组件以及版本7所引入的新特性。 ### Java EE(Java Platform, Enterprise Edition)概述 Java EE是Java...
《The Java EE 7 Tutorial》是一份针对Java EE 7平台的官方教程,旨在帮助开发者掌握Java EE 7的最新技术。Java EE(Java Platform, Enterprise Edition)是一个用来开发企业级应用的平台,它包括了一系列的标准和...
《Java EE 6 教程,第一卷》是Sun Microsystems为开发者提供的一份详尽的指南,旨在深入解析Java EE 6平台的基本概念、架构和关键特性。此教程由Sun Microsystems编写,出版于2009年,是理解Java企业版(Java EE)第...
Java EE 7(Java Platform, Enterprise Edition 7)是Java平台的一个版本,专注于为企业级应用程序开发提供服务。这个教程中的examples代码是学习Java EE 7技术的重要资源,它与官方教程紧密配合,帮助开发者深入...
《Java EE 5 Tutorial》是Java企业版5(Java Platform, Enterprise Edition 5,简称Java EE 5)的官方教程,旨在帮助开发者理解和掌握在Java平台上构建分布式、多层的企业级应用程序。本教程以CHM(Compiled ...
在Java EE 6 tutorial的example代码中,这个文件可能详细阐述了使用、修改和分发这些代码的条款和条件。阅读并遵守这些许可条款对于合法使用这些学习资源至关重要。 "examples"目录是核心部分,它包含了各种Java EE...
### Java EE 6 教程(第一卷):基础知识概览 #### 一、概述 《Java EE 6 教程》(第一卷)是一本详细介绍Java Platform, Enterprise Edition (Java EE) 6版本的基础概念和技术细节的专业书籍。本书由Sun ...
《Java EE5 Tutorial》是Java企业版5(Java EE 5)的重要教程,它为开发者提供了详尽的指导,帮助他们理解和掌握Java EE 5平台的核心技术和开发实践。本教程以CHM(Microsoft Compiled HTML Help)格式呈现,方便在...