问题描述
根据上述文档:
如果要映射到现有数据库,并且表没有区分符列,您仍然可以使用
@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()
。可以使用设置这些Expression
对象DescriptorCustomizer
。
类提取器必须能够确定并从数据库行返回类类型。通常,我们需要替换一个鉴别符列,即
- 列名对于给定的实体类型是唯一的
- 基于根实体给定列的值的条件
假设层次结构中的每个继承实体类型都有一个具有唯一名称的列:
@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
polymorphicResults = em.createQuery(“SELECT p FROM Person p”) .getResultList(); -
分别检索会员或客户列表
List
concreteResults = em.createQuery(“SELECT a FROM Affiliate a”) .getResultList(); List
concreteResults = em.createQuery(“SELECT c FROM Client c”) .getResultList();
解决方法
我有一个Client和Affiliate类,它是从Person类继承的。正在使用联接的继承策略类型-
它们中的每一个都与父类共享主键。由于没有鉴别符列,我们选择使用DescriptorCustomizer和ClassExtractor。但是它并没有真正让人们知道它是如何工作的,而且代码似乎也没有编译。如果有人给出一个带有代码片段的漂亮示例以供理解,那将是很好的。