【问题标题】:How to make this short in Grails or Hibernate如何在 Grails 或 Hibernate 中缩短它
【发布时间】:2011-10-08 13:21:28
【问题描述】:

我的查询看起来像这样:

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。所以最后这不是一个有效的查询(事实上,如果提供了任何nulls,就会抛出NullPointerException)。

如果不使用大量 if-else,我还没有找到任何方法来重写它。有谁知道如何同时同样简短和有效

注意:真正的查询比这更复杂,所以请不要建议使用 executeQuery 以外的任何东西重写它。

【问题讨论】:

    标签: java hibernate spring grails groovy


    【解决方案1】:

    这通常是针对使用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之外的任何其他东西的要求,但您可能还会问如何只使用螺丝刀来建造房屋,最佳答案仍然是“购买一些其他工具")。

    【讨论】:

    • 问题是我上次检查时因为错误而无法使用标准。但也许你是对的,真的没有办法。
    【解决方案2】:

    我想知道你是否可以使用地图和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 映射中具有非空参数的所有查询元素的列表(这应该更改以匹配查询中使用的映射)。这是一项简单的工作,根据主地图的“键”进行过滤,然后将值与and 连接起来。

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

    【讨论】:

      猜你喜欢
      • 2015-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-26
      • 2016-09-14
      相关资源
      最近更新 更多