从String对象中创建Groovy中的动态闭包 [英] Create dynamically closures in Groovy from a String object
问题描述
我想用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屋!