JPA中如何实现多态关系映射?

在JPA中可以通过@Inheritance和@DiscriminatorColumn注解实现多态关系映射。

@Inheritance注解:

  • 用于标注实体类的继承结构,指定其映射策略。
  • 继承结构的根实体需要标注该注解。

@DiscriminatorColumn注解:

  • 用于指定鉴别器列,存储实体类型信息,方便实体类型的区分与查询。

JPA支持3种继承映射策略:

  • JOINED:每个子类拥有自己的表,并且有外键连接父表。
  • TABLE_PER_CLASS:每个子类拥有自己的表,没有连接关系。
  • SINGLE_TABLE:所有子类共用一张表,通过鉴别器列区分类型。

示例:

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "type")
public abstract class Person { ... }  

@Entity 
public class Employee extends Person { ... }

@Entity
public class Customer extends Person { ... }

上例定义了Person作为根实体,Employee和Customer作为其子类实体,使用SINGLE_TABLE策略映射到同一张表,type鉴别器列区分实体类型。

这个例子的优点是:

  1. 简单方便,所有子类共用一张表,通过discriminator值区分类型。
  2. 避免表连接,提高读取性能。
    缺点是表结构相对复杂,需要discriminator列及各类型专有的字段。

多态关系的查询:

  • 可以通过型别字段查询子类型实体,或者通过实体类型查询其派生实体。
  • 需要使用TREAT或CAST函数进行类型转换。

示例:

// 查询Employee类型  
Query query = em.createQuery("SELECT p FROM Person p WHERE p.type = 'Employee'");  

// 也可以  
Query query = em.createQuery("SELECT p FROM Employee p");  

// 向下转型 
Person p = em.find(Person.class, 1);  
Employee e = (Employee) p;