我有一个 Client 和 Affiliate 类,继承自 Person 类。正在使用联合继承策略类型 - 它们每个都与父类共享主键。由于没有鉴别器列,我们选择使用DescriptorCustomizer 和 ClassExtractor。但它并没有真正说明它是如何工作的,而且代码似乎没有编译。如果有人给出一个带有代码片段的好例子来理解,那就太好了。
问问题
9582 次
1 回答
6
根据提到的文件:
如果您要映射到现有数据库,并且表没有鉴别器列,您仍然可以使用
@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<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();
于 2014-03-15T23:06:48.173 回答