Heim > Java > Aggregieren Sie Unterentitäten in Abfrageergebnissen mithilfe von JPA und QueryDSL

Aggregieren Sie Unterentitäten in Abfrageergebnissen mithilfe von JPA und QueryDSL

PHPz
Freigeben: 2024-02-09 21:00:20
nach vorne
802 Leute haben es durchsucht

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.

Frageninhalt

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());
}
Nach dem Login kopieren

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.
}
Nach dem Login kopieren

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!

Workaround

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();
Nach dem Login kopieren
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());
Nach dem Login kopieren

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!

Quelle:stackoverflow.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage