我在使用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:
OneToMany
Post
JPQL
SELECT p FROM Post p ORDER BY SIZE(p.comments) DESC
但是功能SIZE(...)不能用于在中对其进行排序JPQL。
SIZE(...)
因此,我发现了有关JPA Criteria API,并尝试了以下操作:
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字段(集合)的大小排序?
size
comments
CriteriaBuilder.size(Expression)返回Expression<Integer>您可以在ORDER BY子句中使用的。这行代码:
Expression<Integer>
p.get("comments")
..returns Path<X>扩展Expression<X>为a ,因此可以安全地将返回值用作Collection.size()的参数。
Path<X>
Expression<X>
但是,前面引用的代码行使用的是Path.get()的特定重载版本,这将使编译器无法推断类型参数X。而是将type参数假定为Object。 但是 Collection.size()宣布他的Expression-parameter为带有“上限”的“参数化类型” Collection( 这在我的回答中对CriteriaBuilder.size()的首次引用中并未准确反映,StackOverflow坚持擦除方法签名中的类型。请参阅JavaDocs! )。因此,我们必须显式提供类型参数。
Object
Collection
尝试这个:
cq.orderBy(cb.desc(cb.size(p.<Collection>get("comments"))));