开发者

grails paginate with a list from a 1:m relationship

In the case below an author object has an existing list of 'books'. How do you paginate through this list of books if the controller 开发者_StackOverflow社区already has an 'author' object and you do not want to go back to the DB with another request of 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 ]
}


long time no see!

I would certainly agree with Rob here.

What you will see in the sql logs is multiple queries being made for the author and books in both cases. Grails defaults to lazy loading collections, and so at the statement

def author= Author.findByName(params.id)

You have only loaded the author, not the books.

Adding an extra statement to load the books in the normal paginated way will be more efficient, and more maintainable, as it is cleaner and more obvious what it is doing.

This is the style I normally employ to get this kind of data.

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)  
    }  

    ...  
}

Also, (not sure on this), but the size() statement on the books collection will trigger a count query, but may also trigger other queries too, so it pays when you have such a large data set to be specific in what you get GORM to do.

(updated as per Bills comment below)


I admit I am a grails newbie - I reckon I must be missing something.

So after a lot of messing here is my very ugly solution:

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]
  }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜