7.5 本章小结 本章详细介绍了映射的高级应用,包括多表映射、嵌入映射以及实体的继承映射。其中实体继承映射是本章的重点,实体继承有三种策略。最后讲述了实体继承的高级部分、多态的内容。虽然在实际的项目中,本章的这些内容涉及的并不是很多,但在适合的场合也可以有选择的使用。
7.7.4 继承的设计重构 进一步学习了继承的几种策略,下面对图所设计的类进行重构。重构完成后的类继承关系示意图如图所示。在进行重构是考虑这样几方面的问题:l 基类实体EmployeeEO继承自非实体类BaseEO。这样设计的好处是,可以将非持久化的一些属性和方法放到BaseEO中,这样在实体中则不必须将非持久的方法使用@Transient标注了。l 将Contract
7.4.5 带继承关系的实体查询(多态) 在JPA中,实体多态(polymorphism)的使用与Java的多态相同。实体的多态是指,当查询父类的实体时,也包含其子类实体。下面以7.3.3.4小节中数据表中的数据为例,执行以下查询: /**查询所有的EmployeeEO实体*/ String sql = "SELECT e FROM EmployeeE
7.4.3 继承自非实体类 实体除了可以继承自实体外,也可以继承自没有标注@Entity普通的Java类。非实体类中的属性将不被持久化,而继承它的子类中,属性也将不被持久化。例如有这样一个EmployeeEO实体类,继承自普通的Java类BaseEO,代码如下所示。BaseEO类(非实体)public class BaseEO implements Serializable {
7.4.2 继承自非映射实体类(Mapped Superclasses) JPA规范定义了一种特殊的实体类,这种实体类在实体的多在继承时使用,该类可以不映射为指定的一个表,但该类仍可定义可持久化的属性,这些可以被它的子类继承。这类实体使用标记@MappedSuperclass注释标记。例如,将ContractEmployeeEO实体定义为非映射实体的代码,如下所示:@DiscriminatorValue("contract")@MappedSupercl
7.4.1 继承自抽象(abstract)实体类 之前所讲述的实体都是标注在具体类(concrete)上,事实上,实体也可以标注在抽象类abstract上。例如,将7.3.3小节中使用的EmoloyeeEO实体改成抽象类,代码如下所示:@Entity@Table(name = "tb_employee")@Inheritance(strategy=InheritanceType. SINGLE_TABLE)@Discrim
7.3.5.4 数据表中的数据 同样执行7.3.3.4中执行创建实体的代码后,数据库中的表中的数据如图所示。另外,还有个一个生成这些表主键的表中的数据,如图所示。采用每个实体类保存在一个表继承策略,虽然是最简单、最直观的,但因为不同类分别独立的保存在不同的表中,所以在进行实体查询时,要跨越多个表进行查询,效率不高。
7.3.5.3 映射子类实体 下面来看一下各个子类的实体映射配置,子类实体中的属性将自动映射到改子类所对应的表中。实体RegularEmployeeEO的代码如下所示。RegularEmployeeEO实体@Entity@Table(name = "tb_regular_employee")public class RegularEmployeeEO extends EmployeeEO {
7.3.5.2 映射顶层实体类 在基类使用TABLE_PER_CLASS映射时,只需要指定所映射的表和映射策略,而不需要设置@DiscriminatorColumn 和@DiscriminatorValue,以下为EmployeeEO的代码:@Entity@Table(name = "tb_employee")@Inheritance(strategy = InheritanceType.TABLE_PER_CL
7.3.5.1 表结构 同样是图7.3中类继承关系,采用每个实体保存为一个表的策略时,也需要创建5个表。创建表的SQL脚本如下所示。/*员工表*/CREATE TABLE tb_employee ( id int(20) NOT NULL auto_increment, name varchar(255) , PRIMARY KEY (id));/*正式员工表*/CREATE
7.3.4.4 数据表中的数据 这样映射实体后,同样执行7.3.3.4中执行创建实体的代码后,数据库中的表中的数据如图所示。采用每个实体类保存在一个表的继承策略,虽然避免了表中大量null值的数据,但每个实体是通过关联来获得的。当有多个子类时,进行大量的查询会耗时很大,所以采取此策略时需要注意这些问题。
7.3.4.3 映射子类实体 映射子类时除了要映射子类所对应的表外,还要映射父类表与子类表所关键的主键。例如,映射的RegularEmployeeEO实体代码如下所示:RegularEmployeeEO实体@Entity@Table(name = "tb_regular_employee")@DiscriminatorValue("regular")@PrimaryKeyJoinColumn(n
7.3.4.2 映射顶层实体类 在顶层的基类使用JOINED映射时,与使用SINGLE_TABLE的映射配置类似,不同的是标注的映射策略不同,以下为EmployeeEO的代码:EmployeeEO实体@Entity@Table(name = "tb_employee")@Inheritance(strategy=InheritanceType.JOINED)@DiscriminatorColumn
7.3.4.1 表结构 同样是图7.3中类继承关系,采用每个子类保存为一个表的策略时,需要创建5个表。创建表的SQL脚本如下所示:/*员工表*/CREATE TABLE tb_employee ( id int(20) NOT NULL auto_increment, name varchar(255) , employee_type varchar(32), PRIMARY KEY
7.3.4每个实体子类保存在一个表(JOINED) 每个实体子类保存为一个表中,实际上是对SINGLE_TABLE的扩展,SINGLE_TABLE是把数据保存在一个表中,而JOINED是把一个表拆分,每个子类为一个表。所以采用此中继承策略时,每个实体都需要对应映射一个表。
7.3.3.4 数据表中的数据 这样映射实体后,执行创建以下几个实体的代码: /** 创建EmployeeEO实体 */ EmployeeEO employee = new EmployeeEO(); employee.setName("Janet"); entity
7.3.3.3 映射子类实体 下面来看一下各个子类的实体映射配置,实体RegularEmployeeEO的代码如下所示。RegularEmployeeEO实体@Entity@DiscriminatorValue("regular")public class RegularEmployeeEO extends EmployeeEO{ /** * 属性id