php-Herausgeber Baicao brachte einen Artikel über die Verwendung von JPA und QueryDSL zum Aggregieren von Unterentitäten in Abfrageergebnissen. In diesem Artikel befassen wir uns mit der Handhabung der Abfrageergebnisse von Unterentitäten bei der Durchführung aggregierter Abfragen mit JPA und QueryDSL. Durch das Studium dieses Artikels werden die Leser in der Lage sein, zu verstehen, wie man aggregierte Abfragen für Unterentitäten über JPA und QueryDSL implementiert und genaue und effiziente Abfrageergebnisse erhält. Unabhängig davon, ob Sie Anfänger oder erfahrener Entwickler sind, erhalten Sie in diesem Artikel wertvolles Wissen und Tipps, die Ihnen dabei helfen, JPA und QueryDSL besser zu nutzen, um Untereinheiten in aggregierten Abfragen in realen Projekten zu verarbeiten.
Ich entwickle eine Java-Anwendung mit JPA und QueryDSL und stehe vor der Herausforderung einer Eins-zu-Viele-Beziehungsabfrage. Ich habe drei Einheiten: Artikel, Kommentare und Reaktionen. Jeder Beitrag (einer) kann mehrere Kommentare und Reaktionen (viele) haben. Ich brauche jeden Artikel und seine zusammengefassten Kommentare und Reaktionen.
Das ist mein aktueller Ansatz:
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ät:
@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. }
Diese Methode sollte eine Seite mit Articledetail-Objekten zurückgeben, die jeweils die Artikeldetails, den Autor, Kommentare und Reaktionen enthalten. Das Problem, mit dem ich konfrontiert bin, besteht jedoch darin, dass Kommentare und Reaktionen nicht korrekt unter den jeweiligen Artikeln zusammengefasst werden. Jede Articledetail-Instanz sollte eine Liste mit commentdetail und reactiondetail enthalten, diese werden jedoch als separate Einträge zurückgegeben.
Gibt es eine Möglichkeit, diese Abfrage so zu erstellen, dass Kommentare und Reaktionen unter den jeweiligen Artikeln korrekt zusammengefasst werden? Oder sollte es nach Erhalt der Daten programmgesteuert verarbeitet werden?
Für Vorschläge oder Alternativen wäre ich sehr dankbar!
Die von mir implementierte Lösung umfasst einen zweistufigen Abfrageprozess mit querydsl:
Zuerst erhalte ich die IDs von Artikeln, die bestimmte Bedingungen erfüllen:
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());
Hauptaspekte der Lösung: Nutzen Sie einen zweistufigen Abfrageprozess, um zunächst die Artikel-ID zu erhalten und dann den entsprechenden Artikel durch Aggregieren der Daten abzurufen. Die Verwendung von „groupby().list()“ sowie „projections.constructor()“ ist entscheidend für die korrekte Aggregation von Kommentaren und Reaktionen unter jedem Beitrag. Dieser Ansatz löst effektiv das Problem der Aggregation von Kommentaren und Reaktionen unter den jeweiligen Artikeln und gewährleistet gleichzeitig eine effiziente Datenerfassung und Paging.
Ich hoffe, diese ausführliche Erklärung hilft anderen, die sich in ähnlichen Situationen befinden. Feedback oder Anregungen zur weiteren Optimierung sind jederzeit willkommen!
Das obige ist der detaillierte Inhalt vonAggregieren Sie Unterentitäten in Abfrageergebnissen mithilfe von JPA und QueryDSL. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!