首頁 > Java > 使用 JPA 和 QueryDSL 聚合查詢結果中的子實體

使用 JPA 和 QueryDSL 聚合查詢結果中的子實體

PHPz
發布: 2024-02-09 21:00:20
轉載
795 人瀏覽過

php小編百草帶來了一篇關於使用JPA和QueryDSL聚合查詢結果中的子實體的文章。在這篇文章中,我們將深入探討如何在使用JPA和QueryDSL進行聚合查詢時,處理子實體的查詢結果。透過學習本文,讀者將能夠了解如何透過JPA和QueryDSL實現對子實體的聚合查詢,並獲得準確且高效的查詢結果。無論您是初學者還是有經驗的開發者,本文都將為您提供有價值的知識和技巧,幫助您在實際專案中更好地利用JPA和QueryDSL來處理聚合查詢中的子實體。

問題內容

我正在使用 jpa 和 querydsl 開發 java 應用程序,面臨一對多關係查詢的挑戰。我有三個實體:文章、評論和反應。每篇文章(一篇)可以有多個評論和反應(很多)。我需要獲取每篇文章及其匯總的評論和反應。

這是我目前的方法:

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());
}
登入後複製

實體:

@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.
}
登入後複製

此方法應該傳回一個 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() 對於正確聚合每篇文章下的評論和反應至關重要。 這種方法有效解決了聚合各自文章下的評論和反應的問題,同時確保了高效的數據獲取和分頁。

我希望這個詳細的解釋可以幫助其他面臨類似情況的人。隨時歡迎反饋或進一步優化的建議!

以上是使用 JPA 和 QueryDSL 聚合查詢結果中的子實體的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:stackoverflow.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板