3

我正在使用 Grails 创建一个玩具问答网站,以学习该平台。我有两个域,帖子和标签,它们之间有多对多的关系。我想打印带有标签的帖子列表。

我不能使用延迟获取,因为我会遇到 N+1 选择问题

我也不能使用急切获取,因为它使用左连接,我无法正确分页结果。

因此,我决定使用以下代码手动获取标签:


static def getList(params) {

        ArrayList questions = Question.list(params)

        def questionMap = [:]
        questions.each {
            questionMap.put(it.id, it)
        }

        if(questions.size()>0) {
            Tag.executeQuery('SELECT q.id, t FROM Tag t JOIN t.questions q \
                                WHERE q.id in ( :list ) ', [ list:questions.collect{ it.id } ] ).each { questionMap.get(it[0]).tags.add(it[1]) }
        }

        return questions
}

但是,当我在视图中打印标签时:

<g:each in="${questions}" var="question">
   ${question.title} 
   <g:each in="${question.tags}" var="tag">
      ${tag?.text}
   </g:each>
</g:each>

无论如何都会为每个问题执行一个查询!这里推荐的方法是什么?

4

2 回答 2

1

您的代码的问题是您没有对Tag查询结果做任何事情。此外,为多对多关系设置连接类是一种更好的方法。例如,如果您看到 Spring Security Core 插件,您有UserRole和一个名为UserRole. 是示例类。

所以我给你的建议是:

class Tag {
...
}

class Question{
...
}

class QuestionTag implements Serializable {
  Tag tag
  Question question
  static mapping = {
    id composite: ['tag','question']
    ...
  }
  //need to override equals and hashCode
}

要存储标签的结果,您可以为您的类添加一个临时字段:

class Question { def tags static transients = ['tags'] //移除hasMany. }

您现在可以执行您的HQL,在问题列表中查找问题实例并设置tags属性。而且由于您使用的是不返回单个类的 HQL,因此结果不会映射为Tag对象,因此访问方式略有不同。

当查询选择单个字段或计算值时,HQL 查询可以返回域类实例或指定数据的数组

于 2013-03-20T02:50:24.533 回答
0

你是说

“我也不能使用 Eager fetching,因为它使用左连接,我无法正确分页结果。”

您可以使用 session.createFilter 对关联进行分页。

这个例子(版权 Burt Beckwith)来自Burt Beckwith 的“Chapter 5, Hibernate, session.createFilter”一书中的 Programming Grails

// example from Burt Beckwith's book "Programming Grails", (c) Burt Beckwith
class Branch {
    String name
    List visits
    static hasMany = [visits: Visit]

    List<Visit> getVisitsByPage(int pageSize, int pageNumber) {
        Branch.withSession { session ->
            session.createFilter(visits, '')
                    .setMaxResults(pageSize)
                    .setFirstResult(pageSize * pageNumber)
                    .list()
        }
    }
}

我推荐买这本书

于 2013-03-20T05:30:40.653 回答