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

2022-08-31 15:53:58

如何将休眠参数设置为“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);

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

我的问题:

  1. 为什么不将空字符串正确转换为“is null”(而是错误地创建“=null”)?Hibernate

  2. 重写此查询以使其对 null 安全的最佳方法是什么?使用nullsafe,我的意思是在“状态”字符串为空的情况下,它应该创建一个“是空”?


答案 1
  1. 我相信休眠首先将您的HQL查询转换为SQL,然后它才会尝试绑定您的参数。这意味着它将无法从 重写查询 到 。param = ?param is null

  2. 尝试使用条件 api:

    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();
    

答案 2

这不是Hibernate特有的问题(它只是SQL性质),是的,SQL和HQL都有解决方案:

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

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

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

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

笔记:

问题可能是一个特定的MySql怪癖。我只用甲骨文测试过。

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

对 where 子句进行优先级排序,以便首先检查参数。

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

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

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 ");