我想有一个用于构建查询的实用程序,以便我可以为常见查询添加特异性,而不是一遍又一遍地硬编码类似的查询。例如:
DetachedCriteria query = DeviceConfiguration.where { ... }
while(query.list(max: 2).size() > 1) QueryUtil.addConstraint(query, newConstraint)
但是我在处理涉及多对多关系的查询时遇到了麻烦。
如果我的域类是:
class StringDescriptor {
String name
String stringValue
static hasMany = [ deviceConfigurations: DeviceConfiguration ]
static belongsTo = DeviceConfiguration
}
class DeviceConfiguration {
Integer setting1
Integer setting2
static hasMany = [ stringDescriptors: StringDescriptor ]
}
我的设备配置如下所示:
DeviceConfiguration hondaAccord = new DeviceConfiguration(setting1: 1, setting2: 1)
DeviceConfiguration hondaCivic = new DeviceConfiguration(setting1: 2, setting2: 2)
DeviceConfiguration accord = new DeviceConfiguration(setting1: 3, setting2: 3)
StringDescriptor hondaDescriptor = new StringDescriptor(name: "make", stringValue: "honda")
StringDescriptor civicDescriptor = new StringDescriptor(name: "model", stringValue: "civic")
StringDescriptor accordDescriptor = new StringDescriptor(name: "model", stringValue: "accord")
hondaAccord.addToStringDescriptors(hondaDescriptor)
hondaAccord.addToStringDescriptors(accordDescriptor)
hondaCivic.addToStringDescriptors(hondaDescriptor)
hondaCivic.addToStringDescriptors(civicDescriptor)
accord.addToStringDescriptors(accordDescriptor)
hondaAccord.save(failOnError: true)
hondaCivic.save(failOnError: true)
accord.save(failOnError: true, flush: true)
我希望能够做到这一点:
def query = DeviceCollector.where{ stringDescriptors {name =~ "make" & stringValue =~ "honda"} }
if(query.list(max: 2)?.size() > 1)
def query2 = query.where { stringDescriptors {name =~ "model" & stringValue =~ "civic"} }
if(query2.list(max: 2)?.size() > 1)
//...
但这不起作用 - query2 给出的结果与第一个查询相同。然而,当我这样做时,它完美地工作:
def query = DeviceCollector.where{ stringDescriptors {name =~ "make" & stringValue =~ "honda"} }
if(query.list(max: 2)?.size() > 1)
def query2 = query.where { eq('setting1', 1) }
if(query.list(max: 2)?.size() > 1)
def query3 = query.build { eq('setting2', 1) }
请告知:(
感谢注射器进行编辑
现在我的域名包括这个:
class DeviceConfiguration {
//...
static namedQueries = {
byStringDescriptor { String name, String value ->
stringDescriptors {
ilike 'name', name
ilike 'stringValue', value
}
}
}
}
我尝试将查询串在一起,如下所示:
//Lists hondaAccord and hondaCivic
DeviceConfiguration.byStringDescriptor("make", "honda").list()
//Lists hondaAccord and accord
DeviceConfiguration.byStringDescriptor("model", "accord").list()
// LISTS NOTHING... BUT WHYYYYY?
DeviceConfiguration.byStringDescriptor("make", "honda").byStringDescriptor("model", "accord").list()
我很困惑。又一次。
编辑感谢注射器的更新答案
是的,这是对我有用的命名查询:
class DeviceConfiguration {
//...
static namedQueries = {
byStringDescriptor { List<StringDescriptor> descriptors ->
sizeEq('stringDescriptors', descriptors.size())
stringDescriptors {
or {
for(descriptor in descriptors) {
and {
ilike 'name', descriptor.name
ilike 'stringValue', descriptor.stringValue
}
}
}
}
}
}
}
结果(YAYYY(:)...
StringDescriptor hondaDescriptor = new StringDescriptor(name: "make", stringValue: "honda")
StringDescriptor accordDescriptor = new StringDescriptor(name: "model", stringValue: "accord")
//returns nothing - **check**
def hondaQuery = DeviceConfiguration.byStringDescriptor([hondaDescriptor]).list()
//returns accord configuration - **check**
def accordQuery = DeviceConfiguration.byStringDescriptor([accordDescriptor]).list()
//returns just the hondaAccord configuration - **YESSSSSS**
def hondaAccordQuery = DeviceConfiguration.byStringDescriptorUsingOr([hondaDescriptor, accordDescriptor]).listDistinct()
注射器是我最喜欢的人。
使用 criteria query
或 named queries
. 它们都允许更好的链接
class DeviceConfiguration {
static namedQueries = {
byDescriptors { List vals ->
stringDescriptors {
or{
for( def tuple in vals ){
and{
ilike 'name', "%${tuple[ 0 ]}%"
ilike 'stringValue', "%${tuple[ 1 ]}%"
}
}
}
}
}
}
}
因此,您可以致电:
DeviceConfiguration.byDescriptors( [ [ 'make', 'honda' ], [ 'model', 'accord' ] ] ).findAllBySetting1( 10 )
你应该知道,什么合相是合适的and
或or
更新 2
有这么多and
,你什么也找不到......
如果你启动一个像blah( honda, accord ).list()
这样的查询,它会尝试找到带有name='honda' AND name='accord'
的字符串描述符,这是不可能的,所以它不返回任何结果!
这就是为什么我倾向于认为,您的域模型根本不允许此类查询 - 即使在SQL级别也是如此。
您的属性应清晰可辨,以便您可以通过本田(类型"制造"(和雅阁(类型"模型"(找到它不应该在"模型"中寻找"本田"。
单个DeviceConfiguration
实例可以包含同一type
的多个StringDescriptor
吗?