我正在尝试通过JPA CriteriaBuilder构建一个查询,以查找在给定值列表中具有其id的所有对象。
这就是我创造的:
protected <T> Specification<T> equalsToAnyId(Set<Long> ids) {
return (root, query, builder) -> builder.or(root.getModel().getDeclaredSingularAttributes().stream()
.filter(a -> Collections.singletonList("id").contains(a.getName()))
.map(a -> builder.in(
root.get(a.getName())).value(ids))
.toArray(Predicate[]::new)
);
}
这似乎与任何记录(空结果集)都不匹配。怎么了?
答案 0 :(得分:1)
这似乎是编写简单IN过滤器的一种非常复杂的方式。除非您正在编写某种DAO框架,否则为什么接受root, builder, query
并在整个查询只占用几行时返回Specification
?
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<T> cq = cb.createQuery(entityClass);
Root<T> root = cq.from(entityClass);
cq.where(root.get("id").in(guids));
return getEntityManager().createQuery(cq).getResultList();
如果您想保留方法签名,请执行以下操作:
protected <T> Specification<T> equalsToAnyId(Set<Long> ids) {
return (root, query, builder) -> builder.or(builder.in(root.get("id")).value(ids));
}
虽然你没有指定Specification
是什么(JPA规范中没有这样的类)。
通常,如果您不确定为什么查询不返回您期望的数据,请通过persistence.xml
中的提供程序特定属性打开SQL日志记录,例如: hibernate.show_sql
用于休眠,或者通过启用持久性提供程序的调试/精细日志记录,例如: org.hibernate.SQL
作为旁注:是的,我们都很高兴java终于拥有lambdas,但这并不意味着我们必须对所有的事情进行lambda :)尤其是你如何流式传输/过滤/映射元模型以获得{{ 1}} ......让我觉得奇怪。