如何在Grails或Hibernate中做这个简短的

时间:2011-10-08 13:21:28

标签: java hibernate spring grails groovy

我的查询看起来像这样:

SomeDomain.executeQuery("""
    from
        SomeDomain x
    where
        x.linkToSomeA = coalesce(:a, x.linkToSomeA) and
        x.linkToSomeB = coalesce(:b, x.linkToSomeB) and
        ...
    """,
    [a: someA, b: someB, ...]
)

预期行为如下:为标准参数提供null后,应忽略此标准。如果提供了null以外的任何内容,则使用该标准。

除了Hibernate不允许在需要域类实例的地方提供null之外,一切都会正常工作。所以最后这不是一个有效的查询(如果提供了任何NullPointerException,实际上会抛出null

我没有找到任何方法来重写这一点而不使用大量的if-else。有没有人知道如何同时对同样简短有效的做出这个?

注意:真正的查询比这更复杂,请不要建议使用executeQuery之外的其他内容重写。

2 个答案:

答案 0 :(得分:3)

这通常是针对使用Criteria api的这类问题:它允许动态构建查询:

Criteria c = session.createCriteria(SomeDomain.class, "x");
if (a != null) {
    c.add(Restrictions.eq("x.linkToSomeA", a));
}
if (b != null) {
    c.add(Restrictions.eq("x.linkToSomeB", b));
}
// ...

这个答案不符合您的要求,不使用除executeQuery以外的任何其他内容,但您可能还会问如何使用螺丝刀以外的其他方式建造房屋,最佳答案仍然是“购买一些其他工具“)。

答案 1 :(得分:1)

我想知道你是否可以使用地图和findAll(),如下所示:

def query = [
    'a': 'x.linkToSomeA = :a',
    'b': 'x.linkToSomeB = :b'
].findAll{ k, q -> params[k] != null }.values().join(' and ')

SomeDomain.executeQuery("""
    from
        SomeDomain x
    where
        ${query}
    """,
    params
)

这应返回params映射中具有非null参数的所有查询元素的列表(应更改此列表以匹配查询中使用的映射)。根据主地图的“关键字”过滤掉,然后用and加入值,这是一个简单的工作。

注意,有一个潜在的问题,那就是根本没有参数。在这种情况下,您需要检查query是否为空或提供后备方法。