Hibernate:如何使用HQL设置NULL查询参数值?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hibernate:如何使用HQL设置NULL查询参数值?相关的知识,希望对你有一定的参考价值。

如何将Hibernate参数设置为“null”?例:

Query query = getSession().createQuery("from CountryDTO c where c.status = :status  and c.type =:type")
.setParameter("status", status, Hibernate.STRING)
.setParameter("type", type, Hibernate.STRING);

在我的例子中,状态String可以为null。我调试了这个,然后hibernate然后生成一个像这样的SQL字符串/查询.... status = null ...然而这在mysql中不起作用,因为正确的SQL语句必须是“status is null”(Mysql不理解status = null和将此值计算为false,以便根据我读过的mysql文档,不会为查询返回任何记录...)

我的问题:

  1. 为什么qazxsw poi没有正确地将空字符串转换为“is null”(而且错误地创建了“= null”)?
  2. 重写此查询以使其为空安全的最佳方法是什么?使用nullsafe,我的意思是,如果“status”字符串为null,则应该创建“is null”?

非常感谢你!蒂姆

答案
  1. 我相信hibernate首先会将您的HQL查询转换为SQL,然后才会尝试绑定您的参数。这意味着它无法将查询从Hibernate重写为param = ?
  2. 尝试使用Criteria api: param is null
另一答案

这似乎也有效 - >

where ((:orderItemId is null) OR (orderItem.id != :orderItemId))

顺便说一句,我对此很新,所以如果出于任何原因这不是一个好主意,请告诉我。谢谢。

另一答案

这不是Hibernate特定的问题(它只是SQL本质),是的,有一个SQL和HQL的解决方案:

@Peter Lang有正确的想法,你有正确的HQL查询。我想你只需要一个新的清理运行来获取查询更改;-)

以下代码绝对有效,如果您将所有查询保存在orm.xml中,那就太棒了

Criteria c = session.createCriteria(CountryDTO.class); c.add(Restrictions.eq("type", type)); c.add(status == null ? Restrictions.isNull("status") : Restrictions.eq("status", status)); List result = c.list();

如果参数String为null,则查询将检查行的状态是否也为空。否则它将与等号进行比较。

笔记:

问题可能是特定的MySql怪癖。我只用Oracle测试过。

以上查询假定存在c.status为null的表行

优先考虑where子句,以便首先检查参数。

参数名称“type”可能是SQL中的保留字,但它应该无关紧要,因为它在查询运行之前被替换。

如果你需要跳过:status where_clause;你可以像这样编码:

from CountryDTO c where ((:status is null and c.status is null) or c.status = :status) and c.type =:type

它相当于:

from CountryDTO c where (:status is null or c.status = :status) and c.type =:type
另一答案

sql.append(" where "); if(status != null){ sql.append(" c.status = :status and "); } sql.append(" c.type =:type "); 是显式的,表示Object值必须为非null。遗憾的是,如果传入null,它不会抛出异常。

另一种选择是javadoc for setParameter(String, Object),它允许空值,但我不确定setParameter(String, Object, Type)参数在这里最合适。

另一答案

看来你必须在HQL中使用Type(如果存在多个具有零潜力的参数,则可能导致复杂的排列。)但这是一个可能的解决方案:

is null
另一答案

我没试过这个,但是当你使用String statusTerm = status==null ? "is null" : "= :status"; String typeTerm = type==null ? "is null" : "= :type"; Query query = getSession().createQuery("from CountryDTO c where c.status " + statusTerm + " and c.type " + typeTerm); if(status!=null){ query.setParameter("status", status, Hibernate.STRING) } if(type!=null){ query.setParameter("type", type, Hibernate.STRING) } 两次检查:status时会发生什么?

NULL
另一答案

HQL支持Query query = getSession().createQuery( "from CountryDTO c where ( c.status = :status OR ( c.status IS NULL AND :status IS NULL ) ) and c.type =:type" ) .setParameter("status", status, Hibernate.STRING) .setParameter("type", type, Hibernate.STRING); ,允许丑陋的解决方法,如:

coalesce
另一答案

对于实际的HQL查询:

where coalesce(c.status, 'no-status') = coalesce(:status, 'no-status')
另一答案

您可以使用

FROM Users WHERE Name IS NULL

代替

Restrictions.eqOrIsNull("status", status)
另一答案

这是我在Hibernate 4.1.9上找到的解决方案。我必须将一个参数传递给我的查询,有时可能有值NULL。所以我通过了使用:

status == null ? Restrictions.isNull("status") : Restrictions.eq("status", status)

之后,我在查询中使用以下where子句:

setParameter("orderItemId", orderItemId, new LongType())

正如您所看到的,我使用的是Query.setParameter(String,Object,Type)方法,我无法使用我在文档中找到的Hibernate.LONG(可能是旧版本)。有关type参数的完整选项集,请检查org.hibernate.type.Type接口的实现类列表。

希望这可以帮助!

以上是关于Hibernate:如何使用HQL设置NULL查询参数值?的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate HQL 查询:如何将集合设置为查询的命名参数?

Hibernate的HQL多表查询

如何在 Hibernate 中执行非多态 HQL 查询?

Hibernate(十四):HQL查询

Hibernate(十三):HQL查询

如何使用 Joda Time 查询 HQL (Hibernate) 中的日期?