我的查询看起来像这样:
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
之外的其他内容重写。
答案 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
是否为空或提供后备方法。