php小编百草带来了一篇关于使用jpa和querydsl聚合查询结果中的子实体的文章。在这篇文章中,我们将深入探讨如何在使用jpa和querydsl进行聚合查询时,处理子实体的查询结果。通过学习本文,读者将能够了解如何通过jpa和querydsl实现对子实体的聚合查询,并获得准确且高效的查询结果。无论您是初学者还是有经验的开发者,本文都将为您提供有价值的知识和技巧,帮助您在实际项目中更好地利用jpa和querydsl来处理聚合查询中的子实体。
问题内容
我正在使用 jpa 和 querydsl 开发 java 应用程序,面临一对多关系查询的挑战。我有三个实体:文章、评论和反应。每篇文章(一篇)可以有多个评论和反应(很多)。我需要获取每篇文章及其汇总的评论和反应。
这是我当前的方法:
public pagefindarticles(pagerequest pagerequest, user currentuser) { var articles = new jpaqueryfactory(entitymanager) .select(projections.constructor(articledetail.class, article.id, projections.constructor(userdetail.class, user.id, user.name, user.username, user.email, user.profilepicture, user.level, user.position), article.content, article.type, projections.list(projections.constructor(commentdetail.class, comment.user.id, comment.article.id, comment.text, comment.timestamp).skipnulls()).skipnulls(), projections.list(projections.constructor(reactiondetail.class, reaction.user.id, reaction.type).skipnulls()).skipnulls(), article.commentcount, article.datecreated, article.datelastmodified )) .from(article) .innerjoin(article.user, user) .leftjoin(article.comments, comment).on(comment.isactive.istrue()) .leftjoin(article.reactions, reaction) .where(article.isactive.istrue(), user.status.eq(status.active), article.user.in(currentuser.getfollowing()) .or(article.user.eq(currentuser))) .offset(pagerequest.getoffset()) .limit(pagerequest.getpagesize()) .orderby(article.id.asc()) .fetch(); return new pageimpl<>(articles, pagerequest, articles.size()); }
实体:
@Entity
public class Article {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;
@OneToMany(mappedBy = "article")
private Set comments;
@OneToMany(mappedBy = "article")
private Set reactions;
// Other fields like content, type, etc.
}
@Entity
public class Comment {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "article_id")
private Article article;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;
// Other fields like text, timestamp, etc.
}
@Entity
public class Reaction {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "article_id")
private Article article;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;
// Other fields like type, etc.
}
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToMany(mappedBy = "user")
private Set articles;
// Other user fields like name, username, email, etc.
}
此方法应该返回一个 articledetail 对象页面,每个对象包含文章的详细信息、作者、评论和反应。但是,我面临的问题是评论和反应没有正确汇总在各自的文章下。每个 articledetail 实例应包含 commentdetail 和 reactiondetail 的列表,但它们作为单独的条目返回。
有没有办法构建此查询以正确聚合各自文章下的评论和反应?或者应该在获取数据后以编程方式处理?
在现实生活中的购物过程,购物者需要先到商场,找到指定的产品柜台下,查看产品实体以及标价信息,如果产品合适,就将该产品放到购物车中,到收款处付款结算。电子商务网站通过虚拟网页的形式在计算机上摸拟了整个过程,首先电子商务设计人员将产品信息分类显示在网页上,用户查看网页上的产品信息,当用户看到了中意的产品后,可以将该产品添加到购物车,最后使用网上支付工具进行结算,而货物将由公司通过快递等方式发送给购物者
任何建议或替代方法将不胜感激!
解决方法
我实现的解决方案涉及使用 querydsl 的两步查询过程:
首先,我获取了满足特定条件的文章的 id:
var articleids = jpaqueryfactory
.select(article.id)
.from(article)
// conditions and joins
.fetch();
var articles = jpaQueryFactory
.select(article)
.from(article)
// Joins for comments and reactions
.where(article.id.in(articleIds))
.transform(groupBy(article.id).list(
Projections.constructor(ArticleDetail.class,
// Projection fields
)));
return new PageImpl<>(articles, pageRequest, articles.size());
解决方案的关键方面: 利用两步查询过程首先获取文章 id,然后通过聚合数据检索相应的文章。 使用 groupby().list() 以及 projections.constructor() 对于正确聚合每篇文章下的评论和反应至关重要。 这种方法有效解决了聚合各自文章下的评论和反应的问题,同时确保了高效的数据获取和分页。
我希望这个详细的解释可以帮助其他面临类似情况的人。随时欢迎反馈或进一步优化的建议!









