L'éditeur PHP Baicao a publié un article sur l'utilisation de JPA et QueryDSL pour agréger des sous-entités dans les résultats de requête. Dans cet article, nous verrons comment gérer les résultats des requêtes des sous-entités lors de l'exécution de requêtes agrégées à l'aide de JPA et QueryDSL. En étudiant cet article, les lecteurs seront en mesure de comprendre comment implémenter des requêtes agrégées sur des sous-entités via JPA et QueryDSL, et d'obtenir des résultats de requête précis et efficaces. Que vous soyez un développeur débutant ou expérimenté, cet article vous fournira des connaissances et des conseils précieux pour vous aider à mieux utiliser JPA et QueryDSL pour gérer les sous-entités dans les requêtes agrégées dans des projets réels.
Je développe une application Java utilisant jpa et querydsl et je suis confronté au défi de la requête relationnelle un-à-plusieurs. J'ai trois entités : Articles, Commentaires et Réactions. Chaque message (un) peut avoir plusieurs commentaires et réactions (plusieurs). J'ai besoin d'obtenir chaque article et ses commentaires et réactions regroupés.
Voici mon approche actuelle :
public page<articledetail> findarticles(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()); }
Entité :
@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<Comment> comments; @OneToMany(mappedBy = "article") private Set<Reaction> 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<Article> articles; // Other user fields like name, username, email, etc. }
Cette méthode doit renvoyer une page d'objets articledetail, chacun contenant les détails de l'article, l'auteur, les commentaires et les réactions. Cependant, le problème auquel je suis confronté est que les commentaires et réactions ne sont pas correctement regroupés sous leurs articles respectifs. Chaque instance de articledetail doit contenir une liste de commentdetail et de réactiondetail , mais elles sont renvoyées sous forme d'entrées distinctes.
Existe-t-il un moyen de construire cette requête pour regrouper correctement les commentaires et réactions sous leurs articles respectifs ? Ou doit-il être traité par programme après avoir obtenu les données ?
Toutes suggestions ou alternatives seraient grandement appréciées !
La solution que j'ai mise en œuvre implique un processus de requête en deux étapes utilisant querydsl :
Tout d'abord, je récupère les identifiants des articles qui répondent à certains critères :
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());
Aspects clés de la solution : Utilisez un processus de requête en deux étapes pour obtenir d’abord l’identifiant de l’article, puis récupérez l’article correspondant en agrégeant les données. L'utilisation de groupby().list() ainsi que de projections.constructor() est cruciale pour regrouper correctement les commentaires et les réactions sous chaque publication. Cette approche résout efficacement le problème du regroupement des commentaires et des réactions sous leurs articles respectifs tout en garantissant une acquisition et une pagination efficaces des données.
J'espère que cette explication détaillée aidera d'autres personnes confrontées à des situations similaires. Les commentaires ou suggestions pour une optimisation ultérieure sont toujours les bienvenus !
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!