JPA 2.0提供了一种使用JPQL表达式TYPE按子类进行过滤的方法,例如:
SELECT e
FROM entity e
WHERE TYPE(e) = :entityType
其中,参数entityType是鉴别器列的值。
考虑到鉴别器列似乎不受限制,建议使用JPA标准构建器实现相同的方法是什么?
我使用的是JPA 2.1,到目前为止唯一能够将鉴别器列映射为Java实体中的只读字段的解决方案,但我不确定这是否是受支持的功能。
答案 0 :(得分:7)
常见查询示例are here
示例:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery cq = cb.createQuery();
Root e = cq.from(Entity.class);
cq.where(cb.equal(e.type(), entityType));
Query query = em.createQuery(cq);
List<Entity> result = query.getResultList();
答案 1 :(得分:2)
您可以使用路径类型方法as documented here:
Predicate p = cb.equal(e.type(), cb.literal(Entity.class));
答案 2 :(得分:0)
如果您只想检查表达式的 exact 类型,请如上所述使用Path.type()
。
但是,如果您想要与Java的instanceof
运算符等效的Criteria API,唯一的方法是显式列出所有子类型Class
对象。但这会使您的代码不易将来进行重构等。
这是一个提供了JPAUtil.instanceOf()
方法的实用程序类,可以解决该问题:
/**
* JPA utility methods.
*/
public final class JPAUtil {
private JPAUtil() {
}
/**
* Build an IN predicate from a collection of possible values.
*/
public static <T> Predicate in(CriteriaBuilder builder, Expression<T> expr, Iterable<? extends T> values) {
final CriteriaBuilder.In<T> in = builder.in(expr);
values.forEach(in::value);
return in;
}
/**
* Build an "instanceof" predicate.
*/
@SuppressWarnings("unchecked")
public static Predicate instanceOf(EntityManager entityManager, Path<?> path, Class<?> type) {
final Set<Class<?>> subtypes = entityManager.getMetamodel().getManagedTypes().stream()
.map(ManagedType::getJavaType)
.filter(type::isAssignableFrom)
.collect(Collectors.toSet());
return JPAUtil.in(entityManager.getCriteriaBuilder(), (Expression<Class<?>>)path.type(), subtypes);
}
}