grails - Grails:如何最好地构造一个休眠条件构建器来搜索与域实例的 'hasMany'关系

标签 grails hibernate-criteria

我正在执行grails项目,并希望利用休眠条件构建器来搜索域对象的实例。我想找到其中“hasMany”关系之一包含具有某些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
  • 查找蓝色,小号和brandx产品。因此,在这种情况下,我应该只返回产品2。

  • 方案2
  • 查找红色或蓝色且尺寸较小的产品。因此,产品1和产品2均应退货。

  • 方案3
  • 查找brandx或brandz的产品。因此,所有产品均应退货。

  • 我希望这能涵盖所有情况。

    这是当前尝试的一个示例。
    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休眠标准构建器来实现这一目标吗?请让我知道其他信息是否有帮助。

    在此先感谢您提供的任何指导。

    最佳答案

    您正在寻找的是Groovy的Object.every(Closure)
    断言[1、2、3]。每{it <4} == true
    断言[1、2、3]。每{it <3} == falseevery()方法返回一个 bool(boolean) 值,该 bool(boolean) 值指示Closure是否对集合中的每个项目求值为true。
    不幸的是,没有任何查询方法(where,criteria和HQL)提供等效的every()。但是...您可以使用HQL作弊。
    注意:因为条件查询不支持HQL HAVING子句的等效项,所以条件查询也不在哪里。
    场景1-骇客

    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()]
    
    这个怎么运作
    查询开始于选择所有Product,它们在id列表中具有的任何。只要产品具有至少一个选项,它将被返回。
    这产生了为它具有的每个匹配选项列出Option的副作用。例如,如果Product具有三个Product,则将Product返回三次。 GROUP BY子句使查询可以过滤掉那些重复的 list 。
    但是,这些重复项是此黑客的关键:如果ID列表是唯一列表,并且Option一次不具有相同的Product,则如果重复项的数目相等,则Option具有所有必需的Product。到ID的数量。这就是HAVING子句通过计算Option的数量来完成的。
    场景2和3
    场景2和3可以由同一查询处理。我将放弃一致性并选择一个Criteria查询,因为它最能达到此目的。
    // Example params for scenario 2
    def qparams = [
        or: [1, 2], // These are color Option IDs
        and: 5 // This is a size Option ID
    ]
    
    // Example params for scenario 3
    def qparams = [
        or: [10, 11] // These are brand Option IDs
    ]
    
    Product.withCriteria {
        productOptions {
            option {
                if(qparams.and) eq('id', qparams.and.toLong())
                inList('id', qparams.or.collect({ it.toLong() }))               
            }
        }
    }
    
    总是期望or参数,但是if块仅在指定了and参数的情况下才添加and约束。请注意,这些ID只是选项ID,因此具有一定的灵活性。例如,您可以搜索没有颜色限制的任何颜色。
    关于ID ...
    您会注意到,在我的示例中,我将IDS从Integers转换为Longs。如果您的ID来自数据库,那么它们已经是Longs,因此您可以取出该代码。

    关于grails - Grails:如何最好地构造一个休眠条件构建器来搜索与域实例的 'hasMany'关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32856121/

    相关文章:

    grails - 如何获取grails中一列的所有数据?

    java - Hibernate中如何实现触发器?

    hibernate - Spring JPA Criteria Query group by with to_char 函数

    mysql - 尝试确定此方法参数的来源

    tomcat - Grails 应用程序不会在服务器上创建新日志

    grails - Grails Spring Security UI插件-是否支持组?

    java - Hibernate:Query By Example 等效于关联条件查询

    java - 使用 Hibernate Criteria API 读取

    grails - 如何在Jasper报告中导出PDF报告

    hibernate - 保存对象而不释放锁定?