我正在动态构建createCriteria
。到目前为止,一切都很好:
obj
是我想要返回的域对象rulesList
是一个地图列表,其中包含要搜索的字段、要使用的运算符以及要针对搜索的值
def c = obj.createCriteria()
l = c.list (max: irows, offset: offset) {
switch(obj){ //constrain results to those relevant to the user
case Vehicle:
eq("garage", usersGarage)
break
case Garage:
users {
idEq(user.id)
}
break
}
rulesList.each { rule ->
switch(rule['op']){
case 'eq':
eq("${rule['field']}", rule['value'])
break
case 'ne':
ne("${rule['field']}", rule['value'])
break
case 'gt':
gt("${rule['field']}", rule['value'])
break;
case 'ge':
ge("${rule['field']}", rule['value'])
break
case 'lt':
lt("${rule['field']}", rule['value'])
break
case 'le':
le("${rule['field']}", rule['value'])
break
case 'bw':
ilike("${rule['field']}", "${rule['value']}%")
break
case 'bn':
not{ilike("${rule['field']}", "${rule['value']}%")}
break
case 'ew':
ilike("${rule['field']}", "%${rule['value']}")
break
case 'en':
not{ilike("${rule['field']}", "%${rule['value']}")}
break
case 'cn':
ilike("${rule['field']}", "%${rule['value']}%")
break
case 'nc':
not{ilike("${rule['field']}", "%${rule['value']}%")}
break
}
}
}
}
上面的代码运行良好,与switch语句相比只是有点冗长。但是,如果我想添加功能来选择匹配任何规则或所有规则,该怎么办?我需要有条件地将规则放入or{}
中。我不能做类似的事情
if(groupOp == 'or'){
or{
}
在我浏览规则列表和之前
if(groupOp == 'or'){
}
}
之后。我所能想到的就是重复每个条件的代码:
if(groupOp == 'or'){
or{
rulesList.each { rule ->
switch(rule['op']){
...
}
}
}
}
else{
rulesList.each { rule ->
switch(rule['op']){
...
}
}
现在,代码看起来相当草率和重复。假设我想搜索域对象的属性的属性?(例如:我想退货轮胎是某个品牌的车辆;vehicle.tires.brand,或司机匹配名称的车辆;车辆.司机.名称)。我必须做这样的事情吗:
switch(rule['op']){
case 'eq':
switch(thePropertiesProperty){
case Garage:
garage{
eq("${rule['field']}", rule['value'])
}
break
case Driver:
driver{
eq("${rule['field']}", rule['value'])
}
break
}
break
case 'ne':
...
}
首先,您可以通过使用方法名为的GString来简化您的大切换
case ~/^(?:eq|ne|gt|ge|lt|le)$/:
"${rule['op']}"("${rule['field']}", rule['value'])
break
同样的技巧适用于和/或:
"${(groupOp == 'or') ? 'or' : 'and'}"() {
rulesList.each { rule ->
switch(rule['op']){
...
}
}
}
或者您可以先将闭包分配给一个变量,然后根据需要调用or(theClosure)
或and(theClosure)
。最后,对于"属性的属性"搜索,如果您添加
createAlias('driver', 'drv')
createAlias('garage', 'grg')
到条件闭包的顶部,则可以查询eq('drv.name', 'Fred')
之类的内容,而不必添加中间的driver {...}
或garage {...}
节点。