grails使用1:m关系列表进行分页

时间:2010-10-26 07:53:51

标签: grails paginate

在下面的情况下,作者对象具有现有的“书籍”列表。 如果控制器已经有一个“作者”对象并且您不希望返回到另一个请求,那么如何对这些书籍列表进行分页? Book.findAll(“from book as b where b.author =:author”,[author:author],[max:10,offset:5])

class Author {
   String name
   static hasMany = [ books:book]
}
class Book {
   String title
   static belongsTo = [ author:Author ]
}

2 个答案:

答案 0 :(得分:2)

好久不见!

我肯定会同意罗布在这里。

您将在sql日志中看到的是在两种情况下都为作者和书籍进行了多次查询。 Grails默认为延迟加载集合,因此在语句

def author= Author.findByName(params.id)

您只加载了作者,而不是书籍。

添加额外的语句以正常的分页方式加载书籍将更有效,更易于维护,因为它更清晰,更明显。它正在做什么。

这是我通常用来获取此类数据的样式。

def timeline = {  
    println "timeline[" + params+ "]"  
    if (params.id) {  
    def author= Author.findByName(params.id)   
    def books = Book.withCriteria {  
      eq('author', author)  
      firstResult(5)  
      maxResults(10)  
    }  
    def totalBooks = Book.createCriteria().count {  
      eq(author, author)  
    }  

    ...  
}

此外,(不确定),但书籍集合上的size()语句将触发计数查询,但也可能触发其他查询,因此当您拥有如此大的数据集时,它会付出代价在你得到GORM的事情上。

(根据下面的Bills评论更新)

答案 1 :(得分:0)

我承认我是一个grails新手 - 我想我必须遗漏一些东西。

所以在经历了很多混乱之后,这是我非常难看的解决方案:

def timeline = {
println "timeline[" + params+ "]"
if (params.id) {
  def author= Author.findByName(params.id) 

  def allbooks = author?.books as List

  def max=params.max?:(allbooks.size()>2 ? 2: allbooks.size())
  def offset=params.offset?:(0)

  offset = offset as int
  max = max as int

  def start = offset*max > allbooks.size()-1 ? allbooks.size()-1 : offset*max
  def end = ((offset*max)+max-1) > allbooks.size()-1 ? allbooks.size() -1 : ((offset*max)+max-1)

  def books= allbooks.size() > 0?allbooks[(start)..(end)]:allbooks

  def bookCount = allbooks.size()

  println "max:" + params.max + ""
  println "books.size:" + books.size() + ", bookCount:" + bookCount

  [author, bookCount, books]
  }