【问题标题】:Optional parameters with named query in Hibernate?Hibernate中带有命名查询的可选参数?
【发布时间】:2011-01-27 12:38:03
【问题描述】:

在使用Hibernate 时,是否有任何方法可以在命名查询中指定可选参数(例如,当搜索参数是从表单提供时,并非所有参数都是必需的)?我正在使用本机 SQL 查询,但该问题可能也适用于命名为 HQL 的查询。

我很确定这个问题的答案是否定的,但我还没有在文档中找到明确的答案。

【问题讨论】:

    标签: java hibernate orm hql named-query


    【解决方案1】:

    正如前面提到的 different answerquestion 中提到的,以下 HQL 构造适用于我:

    select o from Product o WHERE :value is null or o.category = :value
    

    如果:value 作为null 传入,则返回所有产品。

    另见Optional or Null Parameters

    请注意,由于this bug,这在某些版本的 Sybase 中不起作用,因此以下是替代方法:

    select o from Product o WHERE isnull(:value, 1) = 1 or o.category = :value
    

    【讨论】:

    • 当使用':value is null'时,我得到错误'非法使用关键字NULL'。使用 'isnull(:value, 1) = 1' 时,出现错误 'The left expression is not a valid expression'。
    • 你也可以使用.. WHERE isnull(:value, o.category) = o.category ..
    • 我们曾经使用此解决方案一段时间,直到我们进行负载测试并意识到由于某种原因,在不使用可选参数的情况下,这会大大降低查询的性能。 (大表,几百万条目,DB2,大约四/五个可选参数)。
    • @Ian Jones Optional or Null Parameters 链接是 404
    【解决方案2】:

    AFAIK,没有这样的事情,所以你必须为此编写一个动态查询。也许看看这个previous answer 展示了如何在 HQL 中执行此操作(您可以转置为 SQL),还展示了 Criteria API 如何使其更简单,因此在我看来更适合这项工作。

    更新:(回答 OP 的评论)使用 Hibernate 处理遗留数据库确实很棘手。也许您可以使用动态本机查询并返回non-managed entities。但从长远来看,事情可能会变得更糟(我不能告诉你)。也许 Hibernate 不是您的最佳选择,而 iBATIS 之类的东西可以为您提供所需的灵活性。

    【讨论】:

    • 谢谢。这和我想的差不多。我熟悉您在其他答案中建议的两种方法,但我被一个噩梦般的遗留数据库模式所困扰,它不太适合我的特定情况下的 Hibernate 方法。到目前为止,我已经让它工作了,但是有一些新的要求我似乎无法使用直接的 Hibernate 映射来满足。对于这种情况,我可能会放弃并使用 iBATIS。将另一种技术添加到堆栈中作为创可贴并不真正令人兴奋,但我想这就是生活。谢谢。
    • 感谢您的更新。我也考虑过这种方法,并且考虑到我正在处理的参数数量,我认为只使用 iBATIS 可能更清洁。感谢您的建议。
    【解决方案3】:

    不幸的是,“可选或空参数”下的解决方案不适用于 IN 列表。 我不得不按以下方式更改查询...

    命名查询定义:

    select ls from KiCOHeader co
    ...
    join lu.handlingType ht
    where (:inHandlingTypesX = 1 OR ht.name in (:inHandlingTypes))
    

    代码:

    Set<KiHandlingTypeEnum> inHandlingTypes = ...
    
    Query query = persistence.getEm().createNamedQuery("NAMED_QUERY");
    query.setParameter("inHandlingTypesX", (inHandlingTypes == null) ? 1 : 0);
    query.setParameter("inHandlingTypes", inHandlingTypes);
    
    List<KiLogicalStock> stocks = query.getResultList();
    

    工作很有趣。

    【讨论】:

      【解决方案4】:

      另一种处理可选列表参数的解决方案是使用COALESCE 函数检查null。 COALESCE is supported by Hibernate 从列表中返回第一个非空参数,当列表中有多个项目时,允许您在不破坏语法的情况下检查列表中的空值。

      带有可选参数和列表参数的 HQL 示例:

      select obj from MyEntity obj
      where ( COALESCE( null, :listParameter ) is null or obj.field1 in (:listParameter) )
        and ( :parameter is null or obj.field2 = :parameter )
      

      这对我来说适用于 SQL Server 方言。

      【讨论】:

      • 这对我不起作用,当未定义 :listParameter 时,hibernate 抱怨 COALESCE(null, )。我的解决方案是还传递一个附加参数并以这种方式编写 where 条件:(:listParamterSize = 0 or obj.field1 in (:listParameter))
      • 它可以工作,但必须定义:listParameter,至少为null。这种方案的好处是可以把参数传为null,不需要额外的参数。
      【解决方案5】:

      对于那些有 NULL 值问题的人,另一种选择是使用替代值。在我的例子中,我只为我的类别字段使用了正值,这允许我使用我的备用值 = -1。

      因此,在执行查询之前,可以做一个小验证:

      if(value==null) {
         value = -1;
      }
      ....
      ....
      select p from Product p WHERE :value = -1 or p.category = :value
      

      【讨论】:

        猜你喜欢
        • 2018-04-27
        • 2013-10-22
        • 2011-06-07
        • 2019-04-14
        • 2018-08-11
        • 1970-01-01
        • 1970-01-01
        • 2017-11-29
        • 2014-10-05
        相关资源
        最近更新 更多