Grails Criteria动态和一对多关系的条件

时间:2015-09-17 08:53:10

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

我有一个域类

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

并且

class UrlIndication  {
    UUID id
    String name

    static belongsTo =  Url
   ...

}

我想选择网址,以便它在给定列表UrlIndication中包含所有必需的indicationsId元素。 为此我使用像这样的关联and标准:

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

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

2 个答案:

答案 0 :(得分:1)

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

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

理论上,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工作正常。

答案 1 :(得分:0)

in子句应该:

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