Domain.where {
1 == 0
}.count()
这返回了域类的所有元素。更一般的情况:
Domain.where {
false
}.count()
将返回所有元素;如果我使用其中一个字段并生成错误条件,则结果与预期一致。
我的问题是为什么会发生这种情况(第一种情况)?如果这是一个太天真的问题,请提供一些阅读材料。谢谢!
我使用的grails版本是2.3.6(在较新版本中可能会有所不同吗?)
答案 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 无效。