withCriteria 获取关联对象的列表

withCriteria fetch list of associated objects

我是 Grails 的新手,发现很难理解数据库标准。

谁能帮忙解决以下问题:

这是我的域结构:

-- 评论 --评论组 -- 评论

所以我的域 类 看起来像(简体):

class Comment {
    String commentTitle
    String comment
    CommentGroup commentGroup   
    static hasMany = [commentGroups:CommentGroup]
    static constraints = {
        commentGroup nullable:true
    }
}

class CommentGroup{
    String groupTitle
    static constraints = {
        groupTitle blank:true, nullable:true
    }
}

所以我的评论可以有很多评论组,而评论组又可以有很多评论,但我的评论组没有 hasMany Comments。相反,我通过将 commentGroup 分配给评论来将评论与组相关联。

这正确地保存到 MySQL 数据库,我已经设法使用以下代码撤回带有 commentGroups 的评论:

    def testimonialList = Comment.withCriteria {
        eq 'approved', true
        isNull 'commentGroup'
        order('dateCreated', 'desc')
        order('displayPriority','desc')
        maxResults max
        firstResult offset
    }

我现在需要实现的是通过将当前 Comment CommentGroup 与关联的 Comment CommentGroup 匹配并将它们保存在每个 CommentGroup 下的列表中来拉回每个当前 Comment CommentGroup 的所有评论。

所以我最终得到一个类似于以下的对象结构:

Comment
   CommentGroup1
      Comment1
      Comment2
      Comment3
   CommentGroup2
      Comment1
      Comment2
      Comment3

任何人都可以帮我完成我的条件查询来实现这个。

提前致谢。

要获得您正在寻找的结果,您需要采用不同的方法。

问题

您将域模型描述为:Comment-1-----n--CommentGroup- 1-----n--评论

如果是那样的话,您将能够很容易地实现您的目标。但实际上你得到的是:Comment-1-----n--CommentGroup-n-----1--评论

由于 CommentGroup 没有对其 Comment 的引用,因此从 CommentGroupComment 是一项挑战。

正在寻求解决方案

对于给定的 CommentGroup,您可以这样得到它的 Comment

def comments = Comment.withCriteria {
    eq('commentGroup', commentGroup)
}

如果您有 CommentGroup 的列表,那么您可以像这样获取他们的所有 Comment

def comments = Comment.withCriteria {
    inList('commentGroup', commentGroups)
}

所以你必须:

  1. 运行 获取您感兴趣的 Comment 列表的查询。
  2. 使用那些 Comments 中的 .commentGroups 属性 来获取 CommentGroup 的列表。
  3. 运行 为 CommentGroup 获取 Comment 的第二个查询。
  4. 将所有内容拼凑成您需要的结构;可能使用嵌套 Maps.

前三个步骤如下所示:

def comments = Comment.withCriteria {
    eq 'approved', true
    isNull 'commentGroup'
    ...
}

def commentGroups = comments*.commentGroups

def comments = Comment.withCriteria {
    inList('commentGroup', commentGroups)
}

更好的方法

创建您描述的域模型会简单得多,并具有适合此目的的关联:

class Comment {
    String commentTitle
    String comment
    static belongsTo = CommentGroup
    static hasMany = [commentGroups:CommentGroup]
    static constraints = {
        commentGroup nullable:true
    }
}

class CommentGroup{
    String groupTitle
    static hasMany = [comments: Comment]
    static constraints = {
        groupTitle blank:true, nullable:true
    }
}

有了这个模型,一旦你有了一个 Comment 你就可以得到它的 CommentGroups 和 its Comments

def otherComments = comment.commentGroups*.comments

但是为了更接近您正在寻找的输出,您最好使用 HQL。那是因为条件查询不能 project 根实体。例如,如果您像这样查询 Comments: Comment.withCriteria {...} 您可以 return 那些 Comments (根实体,这是默认行为)或者,您可以 投影 Comment 的属性。是either/or。但是HQL没有这个限制。

def hql = """
SELECT   c, cgs, cs
FROM     Comment as c
         INNER JOIN c.commentGroups as cgs
         INNER JOIN cgs.comments as cs
WHERE    c.approved = true
         // Ignoring, c.commentGroup IS NULL, because it doesn't make sense.
ORDER BY c.dateCreated DESC, c.displayPriority DESC
"""

def result = Comment.executeQuery(hql, null, [maxResults: max])

结果看起来像这样:

[
    [Comment 1, CommentGroup 1, Comment x],
    [Comment 1, CommentGroup 1, Comment y],
    [Comment 1, CommentGroup 1, Comment z],
    [Comment 1, CommentGroup 2, Comment a],
    [Comment 1, CommentGroup 2, Comment b],
    [Comment 1, CommentGroup 2, Comment c],
    [Comment 2, ...],
]

基本上它是您要求的结构,但被展平为查询结果集。

我有一个关于如何查询 GORM 关联的 article,我在其中展示了关联对您可以创建的查询的影响。我想您会发现它有助于了解条件查询。