JPA 2.0 CriteriaQuery 的谓词类型是 class 或任何子 class

JPA 2.0 CriteriaQuery with predicate on type being a class or any subclass of

假设以下实体 类 和层次结构:

@Entity
Class Ticket {

    @ManyToOne(optional = true)
    private Customer customer;    

}

@Entity
Class Customer {}

@Entity
Class Person extends Customer {}

@Class CustomPerson extends Person {}

如何查询具有 customer 类型 Person 或 Person 的任何子类(即 CustomPerson)的所有工单?

我可以轻松地在类型上创建谓词:

Predicate p = criteriaBuilder.equal(Ticket_...type(), criteriaBuilder.literal(Person.class));

但这会过滤掉 CustomPerson

除非有 generic 方法来处理这个问题(在 JPA 2.0 中),如果我能在运行时确定所有扩展 Person 的实体,我就可以解决这个问题;在这种情况下我可以使用

Predicate p = criteriaBuilder.in(Ticket_...type(), listOfPersonSubclasses);

如果在较新版本的 JPA 中没有简单的方法,您可以从底层 Session 获取映射元数据并以编程方式查找所有映射的子类(您可以懒惰地执行并缓存结果)。

获取会话:

org.eclipse.persistence.sessions.Session session = 
     ((org.eclipse.persistence.internal.jpa.EntityManagerImpl) 
                 em.getDelegate()).getSession();

JPA 2.0 不提供通用方法,因此您必须列出所有子class,或者更改查询以使其基于您的 Person class。例如"Select t from Person p, ticket t where t.customer=p"

JPA 2.1 引入了 'treat',它允许您向下转换和操作实体,就好像它是某个 class。由于任何 subclass 也是一个实例,因此它会完全按照您的要求进行过滤。 https://wiki.eclipse.org/EclipseLink/Release/2.5/JPA21#Treat

您可以将其用作连接或在 where 子句中使用,但示例可能是:

"Select t from Ticket t join treat(t.customer as Person) p"