【问题标题】:Grails Criteria dynamic AND conditions for one-to-many relationship一对多关系的 Grails Criteria 动态 AND 条件
【发布时间】:2015-09-17 08:53:09
【问题描述】:

我有一个域类

class Url {
        UUID id
        String url
        static hasMany = [            
            indications:UrlIndication
        ]
        ...
}

还有

class UrlIndication  {
    UUID id
    String name

    static belongsTo =  Url
   ...

}

我想选择网址,以便它在给定列表indicationsId 中包含所有必要的UrlIndication 元素。 为此,我使用了一个关联 and 标准,如下所示:

indications {
                and {
                        indicationsId.each{
                            indication->
                                eq ('id',UUID.fromString(indication as String))
                        }
                    }
            }

但是,我得到的只是一个空结果。你能建议任何修改/其他方法,以便我可以做到这一点吗?提前致谢

【问题讨论】:

    标签: grails dynamic grails-orm one-to-many criteria


    【解决方案1】:

    您的查询返回一个空列表,因为它等同于以下表达式(伪代码):if 1 = 1 and 1 = 2 and 1 = 3

    这样的表达总是错误的。 ininList 由于@innovatism 所描述的原因不起作用。

    理论上,Criteria 的 eqAll() 或 HQL 的 = ALL 可以工作。 但是,我不确定,因为我无法让任何一个工作。

    可行的是使用inList 返回Urls 的子集:至少包含一个UrlIndication ID。然后使用 Groovy 的containsAll() 完成这项工作。

    def ids = indicationsId.collect { UUID.fromString(it as String) }
    
    Url.createCriteria()
        .buildCriteria {
            indications {
                inList 'id', ids
            }
        } 
        .setResultTransformer(org.hibernate.Criteria.DISTINCT_ROOT_ENTITY)
        .list()
        .findAll {
            it.indications.id.containsAll(ids)
        } 
    

    由于查询有可能返回重复的 Url 实例,因此 ResultTransformer 设置为返回唯一列表。

    最后,findAll()containsAll() 一起用于进一步过滤列表。

    使用 eqAll(也许)

    以下内容可能会起作用。 Grails 的 HibernateCriteriaBuilder 发生了一些奇怪的事情,导致 eqAll 方法在根实体中查找属性;完全忽略子标准。所以下面直接使用Hibernate。它对我不起作用,但它已经尽可能接近了。这让我很头疼!

    Url.createCriteria().buildCriteria {}
        .createCriteria('indications', 'i')
        .add(org.hibernate.criterion.Property.forName('i.id').eqAll(org.hibernate.criterion.DetachedCriteria.forClass(UrlIndication)
            .add(org.hibernate.criterion.Restrictions.in('id', ids))
            .setProjection(org.hibernate.criterion.Property.forName('id'))
        ))
        .setResultTransformer(org.hibernate.Criteria.DISTINCT_ROOT_ENTITY)
        .list()
    

    我遇到的问题是我无法让Restrictions.in 工作。 Restrictions.eq 工作正常。

    【讨论】:

    • 最后,我有同样的方法,但是当我想使用分页时,这让我很困扰。您对此有什么建议吗?非常感谢!
    • 我刚刚意识到你是的创新者。哈哈!无论如何,您将无法通过此方法使用 GORM 分页,因为在从 GORM 获取结果后过滤列表时,偏移量/最大值变得无用。您必须对最终列表进行分页。我不确定这样的实现是否已经存在。如果你还有一些键盘油脂,我会用一些可能有用的东西来更新我的答案。
    • @innovatism,最近出现了一个类似的新问题。有一个 HQL 查询可能对您有用。看一看:stackoverflow.com/questions/32856121/…
    【解决方案2】:

    in 子句应该这样做:

    indications {
         'in' 'id', indicationsId.collect{ UUID.fromString indication.toString() }
    }
    

    【讨论】:

    • 这将为您提供包含其中一个元素或两者的网址,而不是包含所有这些元素的网址。
    猜你喜欢
    • 2014-05-15
    • 1970-01-01
    • 1970-01-01
    • 2019-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-18
    • 1970-01-01
    相关资源
    最近更新 更多