一尘不染

构建JPA Criteria API查询-按集合中元素的数量排序

hibernate

我在使用JPA Criteria API构建查询时遇到问题。

实体和重要属性:

@Entity
public class Post {
    @Id int id;
    @OneToMany (mappedBy = "post") Set<Comment> comments;
    //...
}

@Entity
public class Comment {
    @Id int id;
    @ManyToOne Post post;
    //...
}

我需要一个查询,该查询将返回数据库中按评论数(OneToMany在中Post)排序的所有帖子。起初,我认为可以通过以下方式实现JPQL

SELECT p 
FROM Post p 
ORDER BY SIZE(p.comments) DESC

但是功能SIZE(...)不能用于在中对其进行排序JPQL

因此,我发现了有关JPA Criteria API,并尝试了以下操作:

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Post> cq = cb.createQuery(Post.class);
Root<Post> p = cq.from(Post.class);
cq.select(p);
cq.orderBy(cb.desc(p.get("comments")));
List<Post> resultList = em.createQuery(cq).getResultList();

通过此查询,我没有得到正确的结果。我知道我缺少size设置的“注释”,但是不知道如何添加该部分。我不是很熟悉JPA Criteria API。该查询应如何使所有帖子按其comments字段(集合)的大小排序?


阅读 408

收藏
2020-06-20

共1个答案

一尘不染

CriteriaBuilder.size(Expression)返回Expression<Integer>您可以在ORDER
BY子句中使用的。这行代码:

p.get("comments")

..returns Path<X>扩展Expression<X>为a ,因此可以安全地将返回值用作Collection.size()的参数。

但是,前面引用的代码行使用的是Path.get()的特定重载版本,这将使编译器无法推断类型参数X。而是将type参数假定为Object但是
Collection.size()宣布他的Expression-parameter为带有“上限”的“参数化类型” Collection
这在我的回答中对CriteriaBuilder.size()的首次引用中并未准确反映,StackOverflow坚持擦除方法签名中的类型。请参阅JavaDocs!
)。因此,我们必须显式提供类型参数。

尝试这个:

cq.orderBy(cb.desc(cb.size(p.<Collection>get("comments"))));
2020-06-20