我正在开发一个grails项目,并希望利用hibernate标准构建器来搜索域对象的实例。我想找到其中一个有很多人的例子。关系包含具有特定ID的域对象。这是我的意思的一个例子。
域对象
class Product {
static hasMany = [ productOptions: ProductOption ]
}
class ProductOption{
Option option
static belongsTo = [ product: Product ]
}
class Option{
String name
}
这是我的域名结构的简化示例,并不包含所有关系。
Option
可以是尺寸,颜色,品牌等。
我希望实现的示例
假设我有3个产品。
Product 1 is red, small and by brandx
Product 2 is blue, small and by brandx
Product 3 is yellow, medium and by brandz
我需要介绍一些场景。
情景1
场景2
场景3
我希望这涵盖所有情景。
这是当前尝试的一个例子。
def c = Product.createCriteria()
def products = c.list{
and {
productOptions {
'option' {
idEq(1)//1 is the id of the blue option
}
}
productOptions {
'option' {
idEq(5)//5 is the id of the small size option
}
}
productOptions {
'option' {
idEq(10)//10 is the id of the brandx brand option
}
}
}
}
此示例的and
部分不包含所有选项并失败。我如何最好地实现这一目标?我可以使用Grails hibernate条件构建器来实现这一目标吗?如果有其他信息有帮助,请与我们联系。
提前感谢您提供的任何指导。
答案 0 :(得分:2)
您正在寻找的内容相当于Groovy的Object.every(Closure)。
断言[1,2,3]。每个{it< 4} == true 断言[1,2,3]。每个{it< 3} == false
every()
方法返回一个布尔值,指示对于集合中的每个项,Closure的计算结果是否为真。
不幸的是,查询方法(where,criteria和HQL)都没有提供等效的every()
。但是......你可以使用HQL作弊。
注意:Where和Criteria查询都会执行,因为它们不支持等效的HQL HAVING子句。
def ids = [4, 5, 6] // List of Option ids.
Product.executeQuery '''
select prd from Product as prd
join prd.productOptions as prdopts
join prdopts.option as opt
where opt.id in :ids
group by prd
having count(prd) = :count''', [ids: ids.collect { it.toLong() }, count: ids.size().toLong()]
查询首先选择 ID中Product
的 任何 的所有Option
列表。只要产品至少有一个选项,它就会被退回。
这会产生为其拥有的每个匹配选项列出Product
的副作用。例如,如果Product
有三个Option
s,那么产品将返回三次。 GROUP BY子句使查询过滤掉那些重复的列表。
但是,这些重复项是此次攻击的关键:如果ID列表是唯一列表,并且Product
不多次Option
,则{{1}如果重复数量等于ID的数量,则具有所有必需的Product
。这就是HAVING子句通过计算Option
s的数量来实现的。
场景2& 3可以由同一查询处理。我将放弃一致性并选择Criteria查询,因为它最适合此目的。
Product
始终需要或参数,但 if 块仅在和时添加和约束参数已指定。请注意,这些ID都只是选项ID,因此您具有一定的灵活性。例如,您可以搜索没有大小约束的任何颜色。
您会注意到,在我的示例中,我将IDS从Integers转换为Longs。如果您的ID来自数据库,那么它们已经是Longs,因此您可以取出该代码。