代码重构GORM查询

时间:2016-04-18 14:52:15

标签: groovy closures gorm

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

它是:

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

我的问题是,在这一点上:
关闭不运行&#39;,param1上的条件和param2不正确。
和这段代码

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

仍然与param2重复。

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

1 个答案:

答案 0 :(得分:1)

这是一种更简单的方法:

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

上面的示例非常简洁,但如果您真的想使用合成,则可以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。定期关闭不起作用。