Jpa QueryDSL:查询关系和属性

Jpa QueryDSL:查询关系和属性,jpa,querydsl,Jpa,Querydsl,我在JPA中使用QueryDSL 我想查询实体的一些属性,如下所示: QPost post = QPost.post; JPAQuery q = new JPAQuery(em); List<Object[]> rows = q.from(post).where(...).list(post.id, post.name); 并从注释中生成一个子查询sql,如select group_concatc.id,作为c INTERNAR join post,其中c.id=post.idQu

我在JPA中使用QueryDSL

我想查询实体的一些属性,如下所示:

QPost post = QPost.post;
JPAQuery q = new JPAQuery(em);
List<Object[]> rows = q.from(post).where(...).list(post.id, post.name);

并从注释中生成一个子查询sql,如select group_concatc.id,作为c INTERNAR join post,其中c.id=post.id

Querydsl JPA仅限于JPQL的表达能力,因此,使用Querydsl JPA无法实现您的要求。不过,您可以尝试使用Querydsl SQL来表示它。这应该是可能的。另外,由于您不投影实体,但投影文字和集合,所以它可能工作得很好


或者,您可以只加载注释id来加载帖子,然后将id、名称和注释id投影到其他内容。这应该在对访问者进行注释时起作用。

最简单的方法是查询帖子并使用fetchJoin进行注释,但我认为这对于您的用例来说太慢了

我认为您应该简单地投影帖子和评论的所需属性,并在需要时手动对结果进行分组。例如

QPost post=...;
QComment comment=..;

List<Tuple> rows = q.from(post)
// Or leftJoin if you want also posts without comments
.innerJoin(comment).on(comment.postId.eq(post.id))
.orderBy(post.id) // Could be used to optimize grouping
.list(new QTuple(post.id, post.name, comment.id));

Map<Long, PostWithComments> results=...;
for (Tuple row : rows) {
  PostWithComments res = results.get(row.get(post.id));
  if (res == null) { 
    res = new PostWithComments(row.get(post.id), row.get(post.name));
    results.put(res.getPostId(), res);
  }
  res.addCommentId(row.get(comment.id));
}
注意:这种查询不能使用“限制”或“偏移”

另一种方法是,可以优化映射,使1个注释始终是惰性代理,这样就可以在不初始化实际对象的情况下使用属性访问Comment.getId,2使用Post.Comments上的批取*优化集合获取。这样,您可以只查询帖子,然后访问他们评论的id,而不会对性能造成太大影响。在大多数情况下,你甚至不应该需要这些懒惰的代理,除非你的评论非常丰富。如果没有低级别的行处理,这种代码看起来肯定会更好,而且您还可以在查询中使用limit和offset。只需关注您的查询日志,以确保一切按预期进行

*JPA不直接支持批处理抓取,但Hibernate通过映射和Eclipselink通过查询提示支持它


也许有一天Querydsl会支持这种开箱即用的结果分组后处理…

谢谢你的回答。不过我不太明白。。。在SQL方法中,您的意思是我可以在QueryDSL SQL中调用子查询吗?在后一种情况下,您的意思是我应该有一个单独的属性List CommentId,上面有一个公式吗?您可以将子查询与Querydsl SQL一起使用,是的。关于你的第二个问题,不,只是普通属性,但是延迟获取,通过带注释的属性,你可以访问id属性,但是不获取整个对象。谢谢!我以前不知道访问器注释的效果。我将对此进行研究:第一个解决方案看起来非常类似于Playframework的Anorm解析器:您获得感兴趣的列,然后解析/提取/合并/展平结果。我真的希望Querydsl能把这个开箱即用。。。
List<Object[]> rows = q.from(post).where(...).list(post.id, post.name, post.comments);
q.list(post.id, post.name, post.comments.all().id.join())
QPost post=...;
QComment comment=..;

List<Tuple> rows = q.from(post)
// Or leftJoin if you want also posts without comments
.innerJoin(comment).on(comment.postId.eq(post.id))
.orderBy(post.id) // Could be used to optimize grouping
.list(new QTuple(post.id, post.name, comment.id));

Map<Long, PostWithComments> results=...;
for (Tuple row : rows) {
  PostWithComments res = results.get(row.get(post.id));
  if (res == null) { 
    res = new PostWithComments(row.get(post.id), row.get(post.name));
    results.put(res.getPostId(), res);
  }
  res.addCommentId(row.get(comment.id));
}