Grails <where> returns 包含所有条目的 DetachedCriteria
Grails <where> returns DetachedCriteria with all entries
Domain.where {
1 == 0
}.count()
这 return 编辑了域 class 的所有元素。更一般的情况:
Domain.where {
false
}.count()
将return所有元素;如果我使用其中一个字段并设置一个错误条件,则结果符合预期。
我的问题是为什么会发生这种情况(第一种情况)?如果这是一个太幼稚的问题,请建议阅读material。谢谢!
我使用的grails版本是2.3.6(新版本可能不一样?)
我不确定你想要达到什么目的,但这里有一个解释(可能因此有点笼统:)。
你传递给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. Also about creating DSLs with Groovy,尽管这是一个高级主题。
(我简化了 SQL 查询以使其更难以理解,如果您激活 Hibernate 的查询日志或您正在使用的 MySQL/other DB,您会看到它们更大)。
为了说明 Deigote 的解释,这里有一个 非常粗略的 WHERE 查询构建器(实际上只是 WHERE 子句)的实现,使用 criteria criteria格式:
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 无效。
Domain.where {
1 == 0
}.count()
这 return 编辑了域 class 的所有元素。更一般的情况:
Domain.where {
false
}.count()
将return所有元素;如果我使用其中一个字段并设置一个错误条件,则结果符合预期。
我的问题是为什么会发生这种情况(第一种情况)?如果这是一个太幼稚的问题,请建议阅读material。谢谢!
我使用的grails版本是2.3.6(新版本可能不一样?)
我不确定你想要达到什么目的,但这里有一个解释(可能因此有点笼统:)。
你传递给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. Also about creating DSLs with Groovy,尽管这是一个高级主题。
(我简化了 SQL 查询以使其更难以理解,如果您激活 Hibernate 的查询日志或您正在使用的 MySQL/other DB,您会看到它们更大)。
为了说明 Deigote 的解释,这里有一个 非常粗略的 WHERE 查询构建器(实际上只是 WHERE 子句)的实现,使用 criteria criteria格式:
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 无效。