重构巨型单一查询到很多较小的子查询,但结果相同

时间:2013-09-06 07:57:08

标签: hibernate grails groovy gorm detachedcriteria

我有参数列表,我想从中构建查询。 实际上,我已经完成了这项工作,现在我有了一个巨大的方法,我试图重构。 我需要将一个巨大的方法拆分为许多较小的方法,然后将它们合并为一个方法。

我在构建动态查询请求时遇到了麻烦,需要建议。

所以,我查看了文档“6.4.4 Detached Criteria”(http://grails.org/doc/2.2.4/guide/GORM.html#detachedCriteria)。

在“使用子查询的分离标准”一章中找到了下一个示例:

def results = Person.withCriteria {
 gt "age", new DetachedCriteria(Person).build {
     projections {
         avg "age"
     }
 }
 order "firstName"
}

我尝试编写一些将DetachedCriteria作为模拟返回的方法,例如:

DetachedCriteria insertCriteriaLong(def objClass, String cleanKey, def e) {
    new DetachedCriteria(objClass).build {
        if (e.key.toString().endsWith("_from")) {
            gte(cleanKey, e.value as Long)
        } else if (e.key.toString().endsWith("_to")) {
            lte(cleanKey, e.value as Long)
        } else {
            eq(cleanKey, e.value as Long)
        }
    }
}

在调试时,我看到该方法创建了DetachedCriteria对象并使用正确的过滤器(条件)规则填充它。

但是后来我试图从主要请求中调用这个方法,结果我得到了零标准。

    def cr = new DetachedCriteria(objClass).build { 
        insertCriteriaLong(objClass, cleanKey, e)
    }
    cr.list(params)

“cr.list(params)”会返回很多记录。 “insertCriteriaLong”被忽略了。

所以,我想过要重写并返回Criteria或只是一个Closure,但我还是没有找到正确的语法。 例如,我尝试过:

Closure insertCriteriaInteger2 = { String cleanKey, def e ->
    if (e.key.toString().endsWith("_from")) {
        gte(cleanKey, e.value as Integer)
    } else if (e.key.toString().endsWith("_to")) {
        lte(cleanKey, e.value as Integer)
    } else {
        eq(cleanKey, e.value as Integer)
    }
}

你能给我一个提示,我还应该尝试别的什么吗?

我发现下一个问题看起来很相似,但对我来说没什么用处: Grails/Groovy: Modify a "query" closure at runtime

1 个答案:

答案 0 :(得分:0)

好的,我终于找到了解决方案。 Tim_yates,谢谢!

在这里。

DetachedCriteria insertCriteriaLong(DetachedCriteria previousCriteria, String cleanKey, def e) {
    if (e.key.toString().endsWith("_from")) {
        previousCriteria.gte(cleanKey, e.value as Long)
    } else if (e.key.toString().endsWith("_to")) {
        previousCriteria.lte(cleanKey, e.value as Long)
    } else {
        previousCriteria.eq(cleanKey, e.value as Long)
    }
    previousCriteria
}

即使我们有多个标准记录,它也可以工作,例如(例如,代码被简化)。

DetachedCriteria insertCriteriaString(DetachedCriteria previousCriteria, def e) {
    10.times {
        previousCriteria.ilike(e.key, '%' + it + '%')
    }
    previousCriteria
}

实际上,我发现我们一定不能回复任何结果。所以,下一个代码也是正确的:

void insertCriteriaLong(DetachedCriteria currentCriteria, String cleanKey, def e) {
    if (e.key.toString().endsWith("_from")) {
        previousCriteria.gte(cleanKey, e.value as Long)
    } else if (e.key.toString().endsWith("_to")) {
        previousCriteria.lte(cleanKey, e.value as Long)
    } else {
        previousCriteria.eq(cleanKey, e.value as Long)
    }
}