【问题标题】:GORM - dynamic query - Detached Criteria?GORM - 动态查询 - 分离标准?
【发布时间】:2014-11-10 14:14:31
【问题描述】:

我有这样的工作代码:

def criteria = Instance.createCriteria()
def list = criteria.listDistinct {
    eq("saved", true)
    eq("client", client)

    and {
        basicValues {
            eq("fieldA", object.valueA())
            /** CODE BLOCK **/
        }

        customValues {
            eq("fieldB", object.valueB())
            /** CODE BLOCK **/
        }
    }

    or {
        basicValues {
            eq("fieldC", object.valueC())
            /** CODE BLOCK **/
        }

        customValues {
            eq("fieldD", object.valueD())
            /** CODE BLOCK **/
        }
    }
}

如您所见,我正在使用ANDOR 部分创建一些标准。它们都加入了另一个条件(basicValues / customValues 与 Instance 处于 1:n 关系)。 /** 代码块 **/ 部分是一组始终相同的条件。

到目前为止,我在每个/** CODE BLOCK **/ 地方都设置了相同的条件(例如lt("field", 10) 等...)。

我可以把这个/** CODE BLOCK **/ 放到函数中吗?所以这些条件将在一个地方,代码将更具可读性???

【问题讨论】:

    标签: sql hibernate grails grails-orm


    【解决方案1】:

    这是一种您可以在纯 groovy 中将语句保存在闭包中的方法(class Deleg 的所有部分都是为了模拟您的场景):

    class Deleg {
      def invoked = []
    
      def execute(fn) {
        fn.delegate = this
        fn()
      }
    
      def and(closure) { execute(closure) }
      def or(closure) { execute(closure) }
    
      def methodMissing(String method, args) {
        invoked << [method, args]
      }
    }
    
    d = new Deleg()
    
    commonOps = { closure -> 
      return {
        closure()
        lower("a")
        upper("b")
      }
    }
    
    fn = {
      and commonOps {
        eq("a")
      }
    
      or commonOps {
        eq("b")
      }
    }
    
    d.execute(fn)
    
    assert d.invoked.size() == 6
    assert d.invoked == [
      ["eq",    ["a"]],
      ["lower", ["a"]],
      ["upper", ["b"]],
      ["eq",    ["b"]],
      ["lower", ["a"]],
      ["upper", ["b"]],
    ]
    

    我不太了解 GORM,但我认为您可以做类似的事情,而您只需要 commonOps 部分。注意它接收并返回一个闭包。

    它的工作原理是返回一个闭包,该闭包执行特定语句,作为闭包参数传​​递,以及通用语句。请注意,返回的闭包不是由您的应用程序调用的,而是由 GORM 本身调用的。

    【讨论】:

    • 我已尝试实施您的解决方案。代码执行进入“commonOps”,但没有在 return { ... } 内执行任何操作
    • 由 GORM 自己执行。也许您可以尝试将System.out.println() 放入commonOps 以检查它是否正在执行。
    • 不,这是错误的,您使用了两个闭包。它必须只有一个,像这样:or commonOps { ... },而不是or { commonOps { ... } }
    【解决方案2】:

    如果您将/** CODE BLOCK**/ 设置为单独的闭包,则可以在您的条件中包含对它的调用。

    def commonCriteria = {
        /** CODE BLOCK **/
    }
    
    def criteria = Instance.createCriteria()
    def list = criteria.listDistinct {
        commonCriteria.delegate = delegate
        eq("saved", true)
        eq("client", client)
    
        and {
            basicValues {
                eq("fieldA", object.valueA())
                commonCriteria()
            }
    
            customValues {
                eq("fieldB", object.valueB())
                commonCriteria()
            }
        }
        ...
    }
    

    【讨论】:

    • 我已经尝试过您的解决方案。在新的闭包 commonCriteria 方法中,例如 ("",""),gt("","") 不知道
    • @Mato.Duris 我遗漏了分配通用标准代表的一行,请再试一次。
    • hmm ...这是个问题,实际上我应该在那里传递什么? like(...), gt(...) 是闭包内部的方法:-/
    • 你应该通过什么地方?
    • 我的意思是:“通用标准删除” - 那是什么样的对象? (不熟悉 :-( ) ...下一个想法是使用 DetachedCriteria,我今天会尝试使用它
    猜你喜欢
    • 1970-01-01
    • 2017-12-07
    • 2012-03-08
    • 1970-01-01
    • 1970-01-01
    • 2014-03-15
    • 1970-01-01
    • 1970-01-01
    • 2011-12-08
    相关资源
    最近更新 更多