Grails <where>返回DetachedCriteria,包含所有条目

时间:2015-08-07 13:50:35

标签: grails gorm criteria

Domain.where {
    1 == 0
}.count()

这返回了域类的所有元素。更一般的情况:

Domain.where {
    false
}.count()

将返回所有元素;如果我使用其中一个字段并生成错误条件,则结果与预期一致。

我的问题是为什么会发生这种情况(第一种情况)?如果这是一个太天真的问题,请提供一些阅读材料。谢谢!

我使用的grails版本是2.3.6(在较新版本中可能会有所不同吗?)

2 个答案:

答案 0 :(得分:2)

我不确定你想要达到的目的,但这里有一个解释(可能因为这个原因有点笼统:)。

传递给where方法的实际上是一个用于指定SQL标准的DSL,它只是使用普通的Groovy语法假装更自然。但是当你执行someProperty != 5 && someOtherProperty == 6时,它不是直接评估,而是转换为最终在SQL查询中select * from Domain where some_property != 5 and some_other_property = 6

由于您没有在条件(1 == 0)中传递对属性的任何引用,因此它将被分离的条件DSL评估者忽略,从而返回select * from domain的结果。您可以尝试例如id != id来查看如何获得一个空列表作为结果。如果您再次检查生成的查询,则会看到包含where id<>id

您可以详细了解where方法:https://grails.github.io/grails-doc/latest/guide/GORM.html#whereQueries

请记住,传递给where方法的是Closure,因此内部代码不会在前面执行,也不一定在声明它的上下文中进行评估。你可以learn more about Groovy Closures。同样关于creating DSLs with Groovy,虽然是一个高级主题。

(我简化了SQL查询以使它们更加不可靠,如果你激活了Hibernate或MySQL /你正在使用的其他数据库的查询日志,你会发现它们更大)。

答案 1 :(得分:0)

为了说明Deigote的解释,这里是使用criteria criteria格式的WHERE查询构建器(实际上只是WHERE子句)的 非常粗略的 实现:

class WhereBuilder {
    def conditions = []

    def eq(column, value) {
        conditions << [
            column: column, 
            operator: '=', 
            value: value]
    }

    def ne(column, value) {
        conditions << [
            column: column, 
            operator: '!=', 
            value: value]
    }

    String toString() {
        'WHERE ' << 
            conditions.collect { 
                "${it.column} ${it.operator} '${it.value}'"
            }.join(' AND ')
    }
}

def builder = new WhereBuilder()
builder.with {
    1 == 0
    false    
    eq 'firstName', 'John'
    ne 'lastName', 'Smith'
}

assert builder.toString() == "WHERE firstName = 'John' AND lastName != 'Smith'"

如您所见,表达式 1 == 0 false 无效。