根据mentioned documentation:
如果您要映射到现有数据库,并且表没有
一个鉴别器列,您仍然可以使用
@ClassExtractor 注释或 <class-extractor> 元素。班上
提取器采用实现ClassExtractor 的类
界面。该类的一个实例用于确定类
用于数据库行的类型。类提取器必须定义一个
extractClassFromRow() 获取数据库 Record 的方法和
Session.
我们需要使用类提取器定义用户定义的层次结构中的根实体:
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@ClassExtractor(PersonClassExtractor.class)
public abstract class Person {
@Id @GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String name;
private int age;
// ...
}
请注意,我们不使用 @Customizer 注释,因为在 JOINED 继承策略的情况下不需要这样做:
如果类提取器与SINGLE_TABLE 继承一起使用,则行
类类型的必须能够在查询中被过滤。这可以是
通过设置onlyInstancesExpression() 或
withAllSubclassesExpression() 用于分支课程。这些可以设置
使用DescriptorCustomizer 到Expression 对象。
类提取器必须能够从数据库行中确定并返回类类型。
一般来说,我们需要替换一个鉴别器列,即
- 列名对于给定的实体类型是唯一的
- 基于根实体的给定列的值的条件
假设层次结构中每个继承的实体类型都有一个具有唯一名称的列:
@Entity
public class Client extends Person {
@Column(name = "CLIENT_SPECIFIC")
private String clientSpecific;
// ...
}
@Entity
public class Affiliate extends Person {
@Column(name = "AFFILIATE_SPECIFIC")
private float affiliateSpecific;
// ...
}
那么类提取器可能如下所示:
public class PersonClassExtractor extends ClassExtractor {
@Override
public Class<?> extractClassFromRow(Record databaseRow, Session session) {
if (databaseRow.containsKey("CLIENT_SPECIFIC")) {
return Client.class;
} else if (databaseRow.containsKey("AFFILIATE_SPECIFIC")) {
return Affiliate.class;
} else {
return Person.class; // this should never happen
}
}
}
List<Person> polymorphicResults = em.createQuery("SELECT p FROM Person p")
.getResultList();
List<Affiliate> concreteResults = em.createQuery("SELECT a FROM Affiliate a")
.getResultList();
List<Client> concreteResults = em.createQuery("SELECT c FROM Client c")
.getResultList();