如何将 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);
在我的例子中,状态字符串可以为 null。我已经调试了这个,然后 hibernate 生成一个像这样的 SQL 字符串/查询 ....status = null
... 然而,这在 MYSQL 中不起作用,因为正确的 SQL 语句必须是“status is null
”(Mysql 不理解 status=null 并将其计算为 false,以便根据我读过的 mysql 文档,查询不会返回任何记录...)
我的问题:
- < p>为什么
Hibernate
不将 null 字符串正确翻译为“is null”(而是错误地创建“=null”)?
-
重写此查询以使其空安全的最佳方法是什么?对于 nullsafe,我的意思是,在“status”字符串为 null 的情况下,它应该创建一个“is null”?
How can I set a Hibernate Parameter to "null"? Example:
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);
In my case, the status String can be null. I have debugged this and hibernate then generates an SQL string/query like this ....status = null
... This however does not Work in MYSQL, as the correct SQL statement must be "status is null
" (Mysql does not understand status=null and evaluates this to false so that no records will ever be returned for the query, according to the mysql docs i have read...)
My Questions:
-
Why doesnt Hibernate
translate a null string correctly to "is null" (and rather and wrongly creates "=null")?
-
What is the best way to rewrite this query so that it is null-safe? With nullsafe I mean that in the case that the "status" String is null than it should create an "is null"?
发布评论
评论(11)
我相信 hibernate 首先将您的 HQL 查询转换为 SQL,然后才尝试绑定您的参数。这意味着它将无法将查询从
param = ?
重写为param is null
。尝试使用 Criteria api:
I believe hibernate first translates your HQL query to SQL and only after that it tries to bind your parameters. Which means that it won't be able to rewrite query from
param = ?
toparam is null
.Try using Criteria api:
这不是一个 Hibernate 特定问题(它只是 SQL 性质),是的,有一个针对 SQL 和 HQL 的解决方案:
@Peter Lang 有正确的想法,并且您有正确的 HQL 查询。我想您只需要一次新的干净运行来获取查询更改;-)
下面的代码绝对有效,如果您将所有查询保留在来自 CountryDTO c 的 orm.xml
中,那么效果会很好,
其中 ((:status 为 null并且 c.status 为 null) 或 c.status = :status) 和 c.type =:type
如果您的参数 String 为 null,则查询将检查该行的状态是否也为 null。否则它将诉诸于与等号进行比较。
注释:
该问题可能是特定的 MySql 怪癖。我只测试过Oracle。
上面的查询假设存在 c.status 为 null 的表行。
where 子句具有优先级,因此首先检查参数。
参数名称“type”可能是 SQL 中的保留字,但这并不重要,因为它在查询运行之前被替换。
如果您需要完全跳过 :status where_clause;您可以像这样编码:
from CountryDTO c where (:status is null or c.status = :status) and c.type =:type
它相当于:
This is not a Hibernate specific issue (it's just SQL nature), and YES, there IS a solution for both SQL and HQL:
@Peter Lang had the right idea, and you had the correct HQL query. I guess you just needed a new clean run to pick up the query changes ;-)
The below code absolutely works and it is great if you keep all your queries in orm.xml
from CountryDTO c where ((:status is null and c.status is null) or c.status = :status) and c.type =:type
If your parameter String is null then the query will check if the row's status is null as well. Otherwise it will resort to compare with the equals sign.
Notes:
The issue may be a specific MySql quirk. I only tested with Oracle.
The above query assumes that there are table rows where c.status is null
The where clause is prioritized so that the parameter is checked first.
The parameter name 'type' may be a reserved word in SQL but it shouldn't matter since it is replaced before the query runs.
If you needed to skip the :status where_clause altogether; you can code like so:
from CountryDTO c where (:status is null or c.status = :status) and c.type =:type
and it is equivalent to:
setParameter(String, Object) 的 javadoc 是明确的,表示 Object 值必须为非空。遗憾的是,如果传入 null,它不会抛出异常。
另一种方法是
setParameter(String, Object, Type)
,尽管确实允许空值我不确定什么Type
参数在这里最合适。The javadoc for
setParameter(String, Object)
is explicit, saying that the Object value must be non-null. It's a shame that it doesn't throw an exception if a null is passed in, though.An alternative is
setParameter(String, Object, Type)
, which does allow null values, although I'm not sure whatType
parameter would be most appropriate here.看来您必须在 HQL 中使用
is null
(如果有多个可能为 null 的参数,这可能会导致复杂的排列。)但这里是一种可能的解决方案:It seems you have to use
is null
in the HQL, (which can lead to complex permutations if there are more than one parameters with null potential.) but here is a possible solution:HQL 支持 合并,允许对于丑陋的解决方法,例如:
HQL supports coalesce, allowing for ugly workarounds like:
我没有尝试这样做,但是当您使用
:status
两次检查NULL
时会发生什么?I did not try this, but what happens when you use
:status
twice to check forNULL
?对于实际的 HQL 查询:
For an actual HQL query:
您可以使用
插入的
You can use
insted of
这是我在 Hibernate 4.1.9 上找到的解决方案。我必须将一个参数传递给我的查询,有时该参数的值为 NULL。所以我通过了 using:
之后,我在查询中使用了以下 where 子句:
如您所见,我正在使用 Query.setParameter(String, Object, Type) 方法,其中我无法使用 Hibernate.LONG我在文档中找到的(可能是旧版本的)。有关类型参数的完整选项集,请查看 org.hibernate.type.Type 接口的实现类列表。
希望这有帮助!
Here is the solution I found on Hibernate 4.1.9. I had to pass a parameter to my query that can have value NULL sometimes. So I passed the using:
After that, I use the following where clause in my query:
As you can see, I am using the Query.setParameter(String, Object, Type) method, where I couldn't use the Hibernate.LONG that I found in the documentation (probably that was on older versions). For a full set of options of type parameter, check the list of implementation class of org.hibernate.type.Type interface.
Hope this helps!
可能有人正在寻找这个
May be someone are looking for this
这似乎也有效 ->
顺便说一句,我对此还很陌生,所以如果出于任何原因这不是一个好主意,请告诉我。谢谢。
this seems to work as wel ->
Btw, I'm pretty new at this, so if for any reason this isn't a good idea, let me know. Thanks.