注意:据说,在本文所指的实体是@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现场。
版权声明:本文博主原创文章。博客,未经同意不得转载。