Hibernate中带有命名查询的可选参数?

Posted

技术标签:

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

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

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

【问题讨论】:

【参考方案1】:

正如前面提到的 different answer 到 question 中提到的,以下 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

【讨论】:

以上是关于Hibernate中带有命名查询的可选参数?的主要内容,如果未能解决你的问题,请参考以下文章

Mathematica 中的可选命名参数

Chocolatey - 在 packages.config 中带有用户确认的可选包

Android Room 的可选查询参数

带有查询 Spring-Boot jpa 1.5 的可选参数

使用argparse的可选命名参数

如何处理 Play 框架中的可选查询参数