JPA实体继承的映射

注:文章中据说的实体指的是被@Entity注解的类。

JPA中对象关系映射通常情况下是一个实体对应一个表,两个实体之间没有任何关系。如果两个实体之间是继承关系,那么该如何映射呢?

JPA中的实体支持继承映射,多态关联,多态查询。抽象类和具体的类都可以是实体,且都可以使用@Entity来注解,映射成实体,并查询封装成一个实体。实体类可以继承非实体类,非实体类也可以继承实体类。

JPA的继承映射有如下几种情况:

一、实体类继承抽象(具体)实体类

抽象类可以指定成为一个实体,抽象实体和具体实体的唯一区别只是抽象实体不能够被直接实例化。抽象实体能够被映射成一个实体并能够作为查询目标。

抽象实体类使用@Entity注解或在XML描述符表示成一个实体。

这种映射相对复杂,后面会专门写一篇文章来举例说明。这里就不再多说。

二、实体类继承映射超类(Mapped Superclasses)

实体可以继承自一个超类,这个超类提供了持久化实体状态(即属性或字段)和映射信息,但它本身不是一个实体。通常情况下,这种超类映射的的目的是定义多个实体共有的状态和映射信息。

映射超类和实体不一样,它不能够被查询,所以不能作为参数传递给EntityManager或Query 接口进行操作。映射超类定义的持久化关系必须是单向的。

抽象类或具体的类都可以作为映射超类,使用@MappedSuperclass注解(或mapped-superclass XML描述符元素)来指定映射超类。

映射超类不会生成单独的表,它的映射信息作用于继承自它的实体类。

映射超类能够像实体类一样被映射,只是它的映射将作用于继承自它的实体类,因为它本身不存在单独的表。当作用于子类时,继承的映射信息将作用于子类对应的表上。子类可以通过@AttributeOverride和AssociationOverride注解或对应的XML描述符元素来覆盖映射超类的映射信息。下面来看一个实例:

package com.mikan;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;

@MappedSuperclass
public class Employee implements Serializable {

	private static final long serialVersionUID = -7674269980281525370L;

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	protected Integer empId;

	@Column
	protected String name;

	// getter/setter方法

}

package com.mikan;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;

@Entity
@Table(name = "FT_EMP")
public class FullTimeEmployee extends Employee {

	private static final long serialVersionUID = 9115429216382631425L;

	// 继承映射超类的empId和name属性

	@Column
	private Double salary;

	// getter/setter方法

}

package com.mikan;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;

@Entity
@Table(name = "PT_EMP")
public class PartTimeEmployee extends Employee {

	private static final long serialVersionUID = -6122347374515830424L;

	// 继承映射超类的empId和name属性

	@Column(name = "hourly_wage")
	private Float hourlyWage;

	// getter/setter方法

}

其中Employee是映射超类,它包括两个字段(即上面所说的状态)和相应的映射信息,只是这些映射信息都由子类实体FullTimeEmployee和PartTimeEmployee继承,它本身不会生成对应的表。只会生成FT_EMP和PT_EMP两个表,这两个表中的字段包括了子类本身的字段和从映射超类中继承的字段。即FT_EMP表的字段为:empId、name、salary,而PT_EMP表的字段为:empId、name、hourly_wage。

三、实体类继承非实体类

一个实体类可以继承一个非实体超类,这个非实体超类可以是具体的类,也可以是抽象类。

这个非实体超类仅被作为一种继承行为,它的状态不会被持久化。所有继承自非实体超类的状态(即属性或字段)在实体子类中都不会被持久化,实体管理器不会管理这些状态。非实体超类上的所有注解都会被忽略。非实体超类不能作为参数传递给EntityManager或Query 接口进行操作。

下面来看一个实例:

public class Cart {
	protected Integer operationCount; // transient state

	public Cart() {
		operationCount = 0;
	}

	public Integer getOperationCount() {
		return operationCount;
	}

	public void incrementOperationCount() {
		operationCount++;
	}
}

@Entity
public class ShoppingCart extends Cart {
	Collection<Item> items = new Vector<Item>();

	public ShoppingCart() {
		super();
	}

	@OneToMany
	public Collection<Item> getItems() {
		return items;
	}

	public void addItem(Item item) {
		items.add(item);
		incrementOperationCount();
	}
}

ShoppingCart对应的表中不会包含operationCount字段。

时间: 2024-10-20 17:32:38

JPA实体继承的映射的相关文章

JPA实体继承实体的映射策略

注:这里所说的实体指的是@Entity注解的类 继承映射使用@Inheritance来注解,它的strategy属性的取值由枚举InheritanceType来定义(包括SINGLE_TABLE.TABLE_PER_CLASS.JOINED,分别对应三种继承策略).@Inheritance注解只能作用于继承结构的超类上.如果不指定继承策略,默认使用SINGLE_TABLE. JPA提供了三种继承映射策略: 1. 一个类继承结构一个表的策略.这是继承映射的默认策略.即如果实体类B继承实体类A,实体

JPA的继承 OOD和关系数据库的 纽带

JPA实体继承的策略共有三种:table per class策略.table per subclass策略 和 Table_PER_Class策略. 我觉得这些一定程度上打通OOD和关系数据库的联系 详细的操作可以参照这位同行的博文 http://zhuchengzzcc.iteye.com/blog/1679496 JPA的继承 OOD和关系数据库的 纽带

Hibernate之jpa实体映射的三种继承关系

在JPA中,实体继承关系的映射策略共有三种:单表继承策略(table per class).Joined策略(table per subclass)和Table_PER_Class策略. 1.单表继承策略 单表继承策略,父类实体和子类实体共用一张数据库表,在表中通过一列辨别字段来区别不同类别的实体.具体做法如下: a.在父类实体的@Entity注解下添加如下的注解: @Inheritance(Strategy=InheritanceType.SINGLE_TABLE)@Discriminator

《Entity Framework 6 Recipes》中文翻译系列 (8) -----第二章 实体数据建模基础之继承关系映射TPT

翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 2-8 Table per Type Inheritance 建模 问题 你有这样一张数据库表,它包含一些额外的信息,这些信息来到一张公共的表.你想使用Table per  Type Inheritance(TPT)继承映射建模. 解决方案 假设你有两张表与一张公共的表密切相关,如图2-17所示,Businiss表与eCommerce表.Retail表有1:0...1关系.最关键的是,eCo

JPA实体类中的注解

@Entity 标注于实体类上,通常和@Table是结合使用的,代表是该类是实体类@Table 标注于实体类上,表示该类映射到数据库中的表,没有指定名称的话就表示与数据库中表名为该类的简单类名的表名相对应,如果是逆向生成表的话就会以简单类名作为表名 如果指定名称,例如@Table(name="tb_user"),就表示映射到数据库中的tb_userz这个表:@Id 标注于属性上,通常是在get方法上,也可以在属性的声明上. 用于表示该属性作为ID主键@GeneratedValue 主键

Hibernate(十)继承结构映射

Hibernate中继承结构映射有三种实现方式: 使用一张表(映射文件名与超类相同) 每个类一张表(抽象类也对应表.每个表中只有当前类中的属性) 每个具体类对应一张表(抽象类不对应表.每个表中都有全部的信息,包括继承过来的信息) 这里以论坛帖子和回复为例. 使用一张表 超类 package test.hibernate.hbmExtends; import java.util.Date; public class Article { private Integer id; private Str

Java SE环境中测试JPA实体的简单方法

Java SE环境中测试JPA实体的简单方法 出于软件质量的考虑,理论上来说我们写的一切代码都要经过测试.JPA的测试不像普通的组件那么方便,因为JPA涉及到数据库,所以集成测试必不可少,像Arquillian这样的测试框架能处理比较复杂的集成测试,但是它的配置相对也更复杂一点,所以本篇文章主要讲一下在Java SE环境中较简单地测试JPA实体(Entity)的方法. 我们需要实现的目标有:1.不需要mysql这样需要额外安装的数据库:2.在SE环境中可以直接测试. 相关工具我们主要用到JUni

ASP.NET Core搭建多层网站架构【4.1-网站数据库实体设计及映射配置】

2020/01/28, ASP.NET Core 3.1, VS2019 摘要:基于ASP.NET Core 3.1 WebApi搭建后端多层网站架构[4.1-网站数据库实体设计及映射配置] 文章目录 此分支项目代码 本章节介绍后台管理的网站数据库实体设计 需求分析 首先要实现的功能有用户登录.角色管理.日志记录 大概有四张表:用户表.密码表.角色表.日志表 日志表: 用户表: 密码表: 角色表: 好像博客园md不支持表格功能?所以只能截图展示,excel表格上传至项目docs文件夹中 字段设计

【Hibernate学习】 ——ORM(四)再次认识实体继承

在信用办时,做失信.守信.黑名单这一块的时候,先把原来的需求看了看,紧接着就开始设计实体,这一块大部分都是相同的信息,所以就设计了一个实体,并且用一个状态标识出来是失信.守信还是黑名单. 在之后的修改中,特别不方便,每次修改这一块,这都要出问题.也就是说每一次都需要自己的实体去维护自己的状态.但是如果我们把这个状态抽出来,就变成了我们公共的去维护这些"状态",这样就大大简化了我们的工作,我们只需要对基本表的信息进行维护就可以了.这就是单表继承. 代码: 父类: @Entity(name