2010-10-26 3 views
0

Dans le cas ci-dessous un objet auteur a une liste existante de «livres». Comment paginez-vous dans cette liste de livres si le contrôleur a déjà un objet 'author' et que vous ne voulez pas retourner à la base de données avec une autre requête de Book.findAll ("de Book as b où b.author = : auteur », [auteur: auteur], [max: 10, offset: 5])grails paginent avec une liste à partir d'une relation 1: m

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

Juste curieux, quel est le problème d'avoir à faire la requête DB? L'une des intentions de la pagination est de * encourager * cette requête DB supplémentaire afin d'éviter que d'énormes collections de données traînent en mémoire. –

+0

@Rob, @Aaron, Pour deux raisons: '1' La liste des livres est déjà là, alors pourquoi devrais-je aller le chercher à nouveau, '2' J'aurai deux méthodes différentes pour obtenir les mêmes données, qui alors les deux ont besoin d'être testés et maintenus séparément. –

Répondre

2

longtemps sans voir!

Je serais certainement d'accord avec Rob ici. Ce que vous verrez dans les journaux sql, ce sont les requêtes multiples effectuées pour l'auteur et les livres dans les deux cas. par défaut Grails aux collections de chargement paresseux, et ainsi à la déclaration

def author= Author.findByName(params.id) 

Vous avez seulement chargé l'auteur, et non pas les livres. Ajouter une instruction supplémentaire pour charger les livres de façon paginée normale sera plus efficace et plus facile à maintenir, car elle est plus propre et plus évidente.

C'est le style que j'utilise normalement pour obtenir ce type de données.

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

    ... 
} 

En outre, (pas sûr à ce sujet), mais la déclaration taille() sur la collection des livres déclenchera un décompte requête, mais peut également déclencher d'autres requêtes aussi, donc il paie quand vous avez une telle données définir pour être précis dans ce que vous obtenez GORM à faire.

(mis à jour selon les projets de loi commentaire ci-dessous)

+0

acclamations David. J'ai eu besoin de citations sur la ligne eq ('auteur', auteur). Cela semble certainement mieux que ma solution. Il dérange toujours si je ne peux pas utiliser author.books directement –

0

Je dois admettre que je suis un débutant Grails - Je pense que je dois manquer quelque chose.

Ainsi, après beaucoup de déconner voici ma solution très laid:

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

pas une bonne idée, comme Rob a déclaré que la requête supplémentaire est bien, laissez le GORM face à la mise en cache et gérer vos préoccupations de base de données, c'est ce qu'il est là pour –

Questions connexes