在下面的情况下,作者对象具有现有的“书籍”列表。 如果控制器已经有一个“作者”对象并且您不希望返回到另一个请求,那么如何对这些书籍列表进行分页? 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 ]
}
答案 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]
}