从String对象中创建Groovy中的动态闭包 [英] Create dynamically closures in Groovy from a String object

查看:149
本文介绍了从String对象中创建Groovy中的动态闭包的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用Grails(GORM)中的Criteria API创建一个查询。
查询必须是这样的:

  MyEntity.createCriteria()。list {
assoc {
parent {
eq(code,val)
}
}
}

我需要的是从String对象动态构建嵌套闭包。上例中的字符串将是assoc.parent.code。我通过点分割字符串(通过执行 String.split(\\\。))但我不知道如何构建嵌套闭包:

  assoc {
父母{
eq(code,val)
}
}

动态地基于上面拆分字符串的数组。

解决方案

那么 createAlias ?您可以尝试如下所示:

  def path =assoc.parent.code

def split = path.split(/\./)

MyEntity.createCriteria()。list {
//这会让你'createAlias(assoc.parent,alias1)'
createAlias split.take(split.size() - 1),alias1

//这会让你'eq(alias1.code,userInput)'
eqalias1 。$ {split [-1]},userInput
}

这段代码不是通用,但你明白了。






更新

不是常规的,但是您可以使用闭包构建一个包含代码的字符串,并使用

  assoc ='assoc.parent.child.name'
split = assoc.split(/\./)
path = split [-2..0] //会让我们'child.parent .assoc';
//我们将从内部构建它

def firstClosure ={eq'$ {split [-1]}','john doe'}
def lastClosure = firstClosure

(实体在路径中){
def criteriaClosure ={$ {entity {$ {lastClosure}}
lastClosure = criteriaClosure
}

assert lastClosure =={assoc {parent {child {eq'name','john doe'}}}}
def builtClosure = new GroovyShell()。evaluate(return + lastClosure)
assert buildClosure instanceof Closure


i would like to create a query with the Criteria API in Grails (GORM). The query will have to be something like this:

MyEntity.createCriteria().list{
   assoc{
      parent{
         eq("code", val)
      }
   }
}

What i need is to build the nested closure dynamically from a String object. The String for the example above will be "assoc.parent.code" . I splitted the String by dot (by doing String.split("\\.") ) but i don't know how to construct the nested closures:

   assoc{
      parent{
         eq("code", val)
      }
   }

dynamically based on the array of the splitted Strings above.

What about createAlias?. You could try something like this:

def path = "assoc.parent.code"

def split = path.split(/\./)

MyEntity.createCriteria().list {
  // this will get you 'createAlias( assoc.parent, alias1 )'
  createAlias split.take( split.size() - 1 ), "alias1"

  // this will get you 'eq(alias1.code, userInput)'
  eq "alias1.${split[-1]}", userInput
}

This snippet is not generic, but you get the idea.


Update

Not conventional, but you can build a string containing the code with the closures and evaluate it using GroovyShell:

assoc = 'assoc.parent.child.name'
split = assoc.split( /\./ )
path  = split[-2..0] // will get us 'child.parent.assoc';
                     // we will build it from inside-out

def firstClosure = "{ eq '${split[-1]}', 'john doe' }"
def lastClosure = firstClosure

for (entity in path) {
  def criteriaClosure =  "{ ${entity} ${lastClosure} }"
  lastClosure = criteriaClosure
}

assert lastClosure == "{ assoc { parent { child { eq 'name', 'john doe' } } } }"
def builtClosure = new GroovyShell().evaluate("return " + lastClosure)
assert builtClosure instanceof Closure

这篇关于从String对象中创建Groovy中的动态闭包的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆