2013-04-11 7 views
5

Nella mia applicazione di gestione delle attività, gli utenti dovrebbero essere in grado di filtrare le attività in base a: assignedTo, priority, status e/o dueDatedinamicamente la creazione di una query basata su params essere passato a un controller

Non sono sicuro su come per creare una query dinamica in quanto creerà una query basata sui parametri disponibili.

Ad esempio:

se ho un URL, ad esempio: task/index?assignedTo=1&status=2

posso costruire una query basata solo su questi due parametri. Il metodo Sono abituato a è il

Task.findAllByAssignedToAndStatus(
    User.get(params.assignedTo), 
    TaskStatus.get(params.status) 
) 

io non, ovviamente, vuole implementare un metodo a secco scrivendo fuori ogni findAllBy query per ogni possibile combinazione di parametri URL.

C'è un buon modo per farlo in graal?

+0

E 'banale per generare il nome cercatore facendo qualcosa come '" findAllBy $ {params.collect {k, v -> k.capitalize()} .join ('And')} "', ma come fa a sapere che 'assignedTo' dovrebbe caricare un'istanza' User' e ' status' dovrebbe fare riferimento a un 'TaskStatus'? –

+0

D'accordo, non vorrei farlo in questo modo. È per una tesi quindi voglio che il codice sia il più pulito possibile. –

+0

Potrei suggerire una query denominata - http://grails.org/doc/2.2.1/ref/Domain%20Classes/namedQueries.html - quindi puoi filtrare per utente e stato. Penso che facciano rock! – marko

risposta

5

sono riuscito a ottenere questo funzionamento utilizzando createCriteria come segue:

sto usando il valore 0 per qualsiasi params se l'utente seleziona 'Tutti' per quel particolare filtro, quindi verrà omessa dalla cui clausola, ovvero nessuna dichiarazione eq() per quel parametro.

Un frammento di codice:

else 
    {  
     def assignedTo = Integer.parseInt(taskParams.assignedTo) 
     def priority = Integer.parseInt(taskParams.priority) 
     def status = Integer.parseInt(taskParams.status) 

     tasks = Task.createCriteria().list {    

      eq("project", Project.get(taskParams.PId)) 

      if(assignedTo > 0) 
       eq("assignedTo", User.get(assignedTo)) 

      if(priority > 0) 
       eq("priority", TaskPriority.get(priority)) 

      if(status > 0) 
       eq("status", TaskStatus.get(status))     
     }   
    } 
    return tasks 
} 
7

Abbiamo implementato sulle classi di dominio per fare questo. In breve, aggiungi piccoli snippet di namedQueries alla tua classe di dominio.

Esempio:

class Employee { 

    String firstname 
    String lastname 
    Integer age 

    static constraints = { 
    } 

    static namedQueries = { 
     filteronFirstname { String inFirstname -> 
      if (inFirstname&& inFirstname?.size() > 0) { 
       ilike 'firstname', "%${inFirstname}%" 
      } 
     } 

     filteronLastname { String inLastname -> 
      if (inLastname && inLastname?.size() > 0) { 
       ilike 'lastname', "%${inLastname}%" 
      } 
     } 

     filteronAgeOlderThen { String ageOlderThen -> 
      if (age && age ?.size() > 0) { 
       gt 'age', ageOlderThen as Integer 
      } 
     } 

    } 
} 

Questo permetterà sottili funzionalità di filtro grana modo da poter costruire 1 metodo di lista che usa tutti i metodi di filtro e seconda di ciò che l'utente dà come input i namedqueries sono uniti tra loro.

Employee.filteronFirstname("John"). 
filterOnLastname("Doe"). 
filteronAgeOlderThen("10"). 
list(params) 
0

La mia soluzione per una dinamica Dove query da URL:

if (params.query) { 
    def classLoader = getClass().getClassLoader(); 
    def query = new GroovyShell(classLoader).evaluate(
      "import myapp.Visit; Visit.where {$params.query}") 
    visits = query.list(params) 
} 

Questo prende i suoi vincoli da un URL simile a questo:

visit/index?query=client.status=='suspect';atHome==false 
Problemi correlati