GORM 查询的代码重构

Code Refactoring of a GORM query

我写了一个代码来从我的数据库中获取一些实体,但代码非常丑陋(代码重复等)并且对于大块实体来说不是很快。 该代码获取所有实体,然后对其进行排序(在内存中),然后获取一系列项目(用于对结果进行分页)。

就是这样:

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
}

虽然这段代码有效.
,但我认为使用标准而不使用重复代码会更有效 这就是我试图简化代码的原因:

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

此时我的问题是:
闭包不是 'run',param1 和 param2 的条件不正确。
和这段代码

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

仍然与 param2 重复。

如何根据条件(即:params.param1?)编写闭包,我尝试使用 Closure c << param1Closure 但它似乎不起作用。

这里有一个更简单的方法:

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

上面的例子还是比较简洁的,但是如果你真的要用composition的话,可以compose where queries。像这样:

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

关键是如果你用一个变量作为闭包调用where(Closure),那么闭包必须转换为DetachedCriteria。常规关闭将不起作用。