【问题标题】:Grails <where> returns DetachedCriteria with all entriesGrails <where> 返回带有所有条目的 DetachedCriteria
【发布时间】:2015-08-07 13:50:34
【问题描述】:
Domain.where {
    1 == 0
}.count()

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

Domain.where {
    false
}.count()

将返回所有元素;如果我使用其中一个字段并设置错误条件,则结果符合预期。

我的问题是为什么会发生这种情况(第一种情况)?如果这是一个过于幼稚的问题,请建议一些阅读材料。谢谢!

我使用的 grails 版本是 2.3.6(新版本可能不同?)

【问题讨论】:

    标签: grails grails-orm criteria


    【解决方案1】:

    我不确定您要达到什么目的,但这里有一个解释(因此可能有点笼统:)。

    您传递给where 方法的内容实际上是一个用于指定SQL 条件的DSL,它只是使用普通的Groovy 语法来假装更自然。但是当您执行someProperty != 5 &amp;&amp; someOtherProperty == 6 时,它不会直接评估,而是转换为以select * from Domain where some_property != 5 and some_other_property = 6 结尾的SQL 查询。

    由于您没有在条件 (1 == 0) 中传递对属性的任何引用,它会被分离的条件 DSL 评估器忽略,从而返回 select * from domain 的结果。例如,您可以尝试执行 id != id 以查看如何获得空列表作为结果。如果您再次检查生成的查询,您会看到包含 where id&lt;&gt;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/其他正在使用的 DB 的查询日志,您会发现它们更大)。

    【讨论】:

    • 感谢您的回答!第三段正是我昨天遇到的情况!我曾怀疑过类似的事情,但我不确定它是否有意义(当时)。我通过将where 中的标准更改为id&lt;0 之类的标准解决了这个问题(只是为了检查它是否确实给出了预期的结果);你的解释解决了/解释了我的问题。再次感谢!
    • 我只需要返回一个没有元素的DetachedCriteria&lt;Domain&gt;,我最初的想法是,如果我在闭包中有一个条件是false,那么它不会给我任何东西(不管对域类属性的任何引用)
    • 啊,我明白了。是的,为此您需要一个错误的条件 - 但在应用于数据库中包含的行时为错误:),与您在推荐中提供的条件完全相同 (id &lt; 0)。
    【解决方案2】:

    为了说明 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 无效。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-16
      • 1970-01-01
      • 2017-08-21
      • 1970-01-01
      相关资源
      最近更新 更多