如何得到hibernate显示在控制台的hql或sql语句?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何得到hibernate显示在控制台的hql或sql语句?相关的知识,希望对你有一定的参考价值。
参考技术A 如何得到hibernate显示在控制台的hql或sql语句?找到hibernate的配置文件--
hibernate.cfg.xml
加入:
<property
name="hibernate.show_sql">true</property>
如果你用spring那么就要:
修改spring里面的配置文件:
...
<property
name="hibernateProperties">
<props>
<prop
key
=
"hibernate.dialect">org.hibernate.dialect.mysqlDialect</prop>
<prop
key
=
"hibernate.show_sql">false</prop>
...
Hibernate:如何使用 HQL 设置 NULL 查询参数值?
【中文标题】Hibernate:如何使用 HQL 设置 NULL 查询参数值?【英文标题】:Hibernate: How to set NULL query-parameter value with HQL? 【发布时间】:2010-01-23 14:21:00 【问题描述】:如何将休眠参数设置为“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);
就我而言,状态字符串可以为空。我已经对此进行了调试,然后休眠然后生成一个像这样的 SQL 字符串/查询 ....status = null
... 但是这在 MYSQL 中不起作用,因为正确的 SQL 语句必须是“status is null
”(Mysql 不明白status=null 并将其评估为 false,因此根据我已阅读的 mysql 文档,不会为查询返回任何记录...)
我的问题:
为什么Hibernate
不能将空字符串正确翻译为“is null”(而是错误地创建“=null”)?
重写此查询以使其成为空值安全的最佳方法是什么?使用 nullsafe 我的意思是在“状态”字符串为空的情况下,它应该创建一个“为空”?
【问题讨论】:
对于那些对解决方案感兴趣的人,我认为 Criteria API 是一种方法。但是我仍然不太相信,因为它会可怕地加载代码并且使用 HQL 会更干净。也许真正的解决方案是实现你自己的 Hibernate 类型(我已经为 ENUM 实现了一个,但是这些自我实现的类型,至少基本的类型比使用 HQL 查询中的休眠类型中的 bulid 有很大的缺点(除非你还扩展了 HQL解析器?)是什么让这是一个巨大的项目,需要大量的 Hibernate 知识......(在第 2 部分继续) 刚刚也遇到了这个……天哪,这真是脑残。 我非常讨厌hibernate,这绝对是愚蠢的 这么多年过去了,有没有不使用 Criteria API 的解决方案? @phpslightly 我不敢相信还没有! 【参考方案1】:我相信 hibernate 首先将您的 HQL 查询转换为 SQL,然后才尝试绑定您的参数。这意味着它将无法将查询从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();
【讨论】:
谢尔盖您好,感谢您的回答。我实际上也使用 Criteria API 实现了它(在您发布答案之前)。但我仍然认为这不是问题的“理想解决方案”。好吧,老实说,有时“奇怪/错误”没有真正好的解决方案....我已将您的答案标记为问题的“解决方案”。 不客气 :) 但是您对理想解决方案有何期望?如果您对标准 api 而不是 hql 感到满意,您可以随时为“null-safe”标准创建自己的工厂方法。 很好的答案!这个简单的修复帮助我查询一个可为空的字段,而无需求助于字符串构建查询!【参考方案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
如果您的参数字符串为空,则查询将检查该行的状态是否也为空。否则会使用等号比较。
注意事项:
问题可能是特定的 MySql 怪癖。我只用 Oracle 测试过。
上述查询假设存在 c.status 为空的表行
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 ");
【讨论】:
为什么不from CountryDTO c where (:status is not null and c.status = :status) and c.type =:type
?
@Alex78191 使用or
,查询将产生:from CountryDTO c where (true) and c.type =:type
,而您的将产生:from CountryDTO c where (false) and c.type =:type
,这将不会给您任何行。
@Alex78191 你也可以试试这个:select 'data' from dual where (1=2)
和这个:select 'data' from dual where (1=1)
看看有什么不同。【参考方案3】:
javadoc for setParameter(String, Object)
是显式的,表示 Object 值必须非空。遗憾的是,如果传入 null,它不会引发异常。
另一种选择是setParameter(String, Object, Type)
,它确实允许空值,虽然我不确定在这里哪个Type
参数最合适。
【讨论】:
你好,斯卡夫曼。非常感谢您的帮助!在问这个问题时,我实际上认为我只是愚蠢地寻找解决方案。但这似乎是hibernate的真正“怪事”。很可能我将不得不编写自己的 Nullable-String-Type 或者我将不得不切换到 Criteria Queries... 在深入挖掘之后,Hibernat.STRING 类型的当前实现似乎不可为空:docjar.com/html/api/org/hibernate/type/StringType.java.html。 (但 MySQL JConnector 不应该正确实现 PreparedStatment.setString 吗??)谢谢 Tim。 仅供参考,其实是JDBC的一个“特性”:bugs.sun.com/bugdatabase/view_bug.do?bug_id=4312435Hibernate使用JDBC的PreparedStatement.setNull()
绑定null
参数【参考方案4】:
您似乎必须在 HQL 中使用 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)
【讨论】:
对我来说看起来像是旧的 sql 查询。坚持这样的标准api。手写 hql 极易出错。【参考方案5】:HQL 支持 coalesce,允许使用以下丑陋的变通方法:
where coalesce(c.status, 'no-status') = coalesce(:status, 'no-status')
【讨论】:
【参考方案6】:我没有尝试这个,但是当你使用: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);
【讨论】:
帮助彼得,非常感谢您的帮助!我不知道为什么,但似乎hibernate总是将(c.status = :status OR(c.status IS NULL AND :status IS NULL)评估为c.status = null(根据我的mysql查询日志)。我也将顺序更改为 (( c.status IS NULL AND :status IS NULL ) OR c.status = :status) ,结果相同。谢谢 Tim【参考方案7】:对于实际的 HQL 查询:
FROM Users WHERE Name IS NULL
【讨论】:
【参考方案8】:你可以使用
Restrictions.eqOrIsNull("status", status)
插入
status == null ? Restrictions.isNull("status") : Restrictions.eq("status", status)
【讨论】:
【参考方案9】:这是我在 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(可能是在旧版本上)。 type参数的全套选项请查看org.hibernate.type.Type接口的实现类列表。
希望这会有所帮助!
【讨论】:
【参考方案10】:这似乎也有效 ->
@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();
顺便说一句,我对此很陌生,所以如果出于任何原因这不是一个好主意,请告诉我。谢谢。
【讨论】:
您不应该使用is
运算符:即... + " t where t.thing " + ((thing == null) ? "is null" : "= :thing")
能否详细说明这两者的区别?
使用= null
会引发异常。尽管它可能取决于您运行哪个 dbms。在 SQL 中你有同样的问题,你也必须使用is null
而不是= null
。 null
的问题是,一些数据库认为它并不是真正的空值,而是一个未确定的值,这意味着 null 不等于 null。因此null
= null
永远不会是真的。见:***.com/questions/5066492/…以上是关于如何得到hibernate显示在控制台的hql或sql语句?的主要内容,如果未能解决你的问题,请参考以下文章
hibernate hsql得到错误节点没有数据类型:org.hibernate.hql.ast.tree.IdentNode
(hibernate)如果我想查询表的总记录数,HQL语句应该怎么写?又如何获得值呢?
为啥得到 org.hibernate.hql.internal.ast.QuerySyntaxException: Path expected for join!加入 3 个表时