2016-04-18 5 views
1

Ich schrieb einen Code, um einige Entitäten aus meiner Datenbank zu bekommen, und der Code ist ziemlich hässlich (Duplikation von Code, etc.) und nicht sehr schnell für große Stück von Entitäten. Der Code ruft alle Entitäten ab, sortiert sie dann (im Speicher) und nimmt dann eine Reihe von Elementen (zum Paginieren der Ergebnisse).Code Refactoring einer GORM-Abfrage

Da ist es:

List<T> retrieveData() { 
    def filterPastEvents = (params.filterPastEvents) ?: 0 
    def entities = retrieveUnsortedData(filterPastEvents).sort { 
     entity1, entity2 -> 
      entity2.criterion1 <=> entity1.criterion1 ?: 
        entity1.criterion2 <=> entity2.criterion2 ?: 
          entity1.criterion3 <=> entity2.criterion3 
    } 
    if (params.offset != null && params.max != null) { 
     return entities.subList(params.offset, Math.min(params.to+1,entities.size())) 
    } else { 
     return entities 
    } 
} 

private List<Entity> retrieveUnsortedData(filterPastEvents) { 

    List<Entity> entityList 
    if (params.param1 && params.params2) { 
     entityList = Entity.findAll({ 
      param1 == params.param1 
      params2 == params.params2 
      endTimeUTC >= filterPastEvents 
     }) 
    } 
    if (params.param1 && !params.params2) { 
     entityList = Entity.findAll({ 
      param1 == params.param1 
      endTimeUTC >= filterPastEvents 
     }) 
    } 
    if (params.params2 && !params.param1) { 
     entityList = Entity.findAll({ 
      params2 == params.params2 
      endTimeUTC >= filterPastEvents 
     }) 
    } 
    if (entityList == null) { 
     entityList = Entity.findAll({ 
      endTimeUTC >= filterPastEvents 
     }) 
    } 
    return entityList 
} 

Ich dachte, es wäre effizienter zu sein, es mit Kriterium zu tun und ohne duplizierten Code obwohl dieser Code funktioniert.
Das ist, was ich versuchte, den Code zu vereinfachen:

List<T> retrieveData() { 

    def filterPastEvents = (params.filterPastEvents) ?: 0 
    Closure closureOrder = { 
     endTimeUTC >= filterPastEvents 
     order('criteria1', 'desc') 
     order('criteria2', 'asc') 
     order('criteria3', 'desc') 
    } 
    Closure param1Closure = {} 
    if (params.param1) { 
     param1Closure = { 
      param1 == params.param1 
     } 
    } 
    Closure param2Closure = {} 
    if (params.param2) { 
     param2Closure = { 
      param2 == params.param2 
     } 
    } 
    return Entity.findAll(max: params.max, offset: params.offset).list { 
     param1Closure 
     param2Closure 
     closureOrder 
    } 
} 

Meine Probleme sind, an dieser Stelle:
der Verschluss nicht ‚run‘ sind, erhalten auf param1 und param2 ist nicht korrekt.
und dieser Code

Closure param1Closure = {} 
    if (params.param1) { 
     param1Closure = { 
      param1 == params.param1 
     } 
    } 

ist immer noch mit param2 dupliziert.

Wie kann ich Schließungen abhängig von den Bedingungen zusammenstellen (dh: params.param1?), Habe ich versucht, Closure c < < param1Closure, aber es scheint nicht zu funktionieren.

Antwort

1

Hier ist ein einfacher Weg:

List<T> retrieveData() { 
    Entity.findAll(max: params.max, offset: params.offset) { 
     if(params.param1) param1 == params.param1 
     if(params.param2) param2 == params.param2 
     if(params.filterPastEvents) endTimeUTC >= filterPastEvent 

     order 'criteria1', 'desc' 
     order 'criteria2', 'asc' 
     order 'criteria3', 'desc' 
    } 
} 

Das obige Beispiel ganz präzise ist, aber wenn Sie wirklich Zusammensetzung verwenden möchten, können Sie compose where queries. Etwas wie folgt aus:

import grails.gorm.DetachedCriteria 

List<T> retrieveData() { 
    ... 
    DetachedCriteria<Entity> param1Closure = (params.param1 ? { param1 == params.param1 } : { }) as DetachedCriteria<Entity> 
    ... 

    def query = Entity.where(param1Closure) 

    query = query.where(param2Closure) 
    query = query.where(closureOrder) 

    return query.list(max: params.max, offset: params.offset) 
} 

Der wichtige Schlüssel ist, dass, wenn Sie where(Closure) mit einer Variablen wie die Schließung nennen, dann muss der Verschluss an einem DetachedCriteria gegossen werden. Eine regelmäßige Schließung wird nicht funktionieren.

+0

Es funktioniert, danke für Ihre Hilfe! – Fabinout