![](/img/trans.png)
[英]Hibernate HQL Query : How to set a Collection as a named parameter of a Query?
[英]Hibernate: How to set NULL query-parameter value with HQL?
如何將休眠參數設置為“空”? 例子:
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);
就我而言,狀態字符串可以為空。 我已經調試了這個,然后休眠然后生成一個像這樣的 SQL 字符串/查詢 .... status = null
... 然而這在 MYSQL 中不起作用,因為正確的 SQL 語句必須是“ status is null
”(Mysql 不理解根據我閱讀的 mysql 文檔,status=null 並將其評估為 false,以便查詢不會返回任何記錄...)
我的問題:
為什么Hibernate
正確地將空字符串轉換為“is null”(而是錯誤地創建“=null”)?
重寫此查詢以使其為空安全的最佳方法是什么? 使用 nullsafe 我的意思是,在“狀態”字符串為空的情況下,它應該創建一個“為空”?
我相信 hibernate 首先將您的 HQL 查詢轉換為 SQL,然后才嘗試綁定您的參數。 這意味着它將無法從param = ?
重寫查詢param = ?
param is null
。
嘗試使用 Criteria 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();
這不是特定於 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 為空,則查詢將檢查行的狀態是否也為空。 否則它將求助於與等號進行比較。
筆記:
問題可能是特定的 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
它相當於:
sql.append(" where ");
if(status != null){
sql.append(" c.status = :status and ");
}
sql.append(" c.type =:type ");
setParameter(String, Object)
的javadoc是明確的,說 Object 值必須是非空的。 遺憾的是,如果傳入 null,它不會引發異常。
另一種方法是setParameter(String, Object, Type)
,這確實允許空值,雖然我不知道什么Type
的參數會在這里是最合適的。
似乎您必須在 HQL 中使用is null
(如果有多個參數可能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)
}
HQL 支持coalesce ,允許丑陋的解決方法,例如:
where coalesce(c.status, 'no-status') = coalesce(:status, 'no-status')
我沒有嘗試這個,但是當你使用:status
兩次來檢查NULL
時會發生什么?
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);
對於實際的 HQL 查詢:
FROM Users WHERE Name IS NULL
您可以使用
Restrictions.eqOrIsNull("status", status)
插入的
status == null ? Restrictions.isNull("status") : Restrictions.eq("status", status)
這是我在 Hibernate 4.1.9 上找到的解決方案。 我不得不將一個參數傳遞給我的查詢,有時它的值可能為 NULL。 所以我通過了使用:
setParameter("orderItemId", orderItemId, new LongType())
之后,我在查詢中使用以下 where 子句:
where ((:orderItemId is null) OR (orderItem.id != :orderItemId))
如您所見,我使用的是 Query.setParameter(String, Object, Type) 方法,我無法使用我在文檔中找到的 Hibernate.LONG(可能是舊版本)。 類型參數的全套選項,查看org.hibernate.type.Type接口的實現類列表。
希望這可以幫助!
這似乎也有效->
@Override
public List<SomeObject> findAllForThisSpecificThing(String thing) {
final Query query = entityManager.createQuery(
"from " + getDomain().getSimpleName() + " t where t.thing = " + ((thing == null) ? " null" : " :thing"));
if (thing != null) {
query.setParameter("thing", thing);
}
return query.getResultList();
}
順便說一句,我對此很陌生,所以如果出於任何原因這不是一個好主意,請告訴我。 謝謝。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.