Sql 休眠并静态运行HQL查询

Sql 休眠并静态运行HQL查询,sql,hibernate,hql,Sql,Hibernate,Hql,我想“干运行”Hibernate HQL查询。也就是说,我想知道Hibernate将从给定的HQL查询执行什么样的实际SQL查询,而不实际对实际数据库执行HQL查询 我可以访问表的hibernate映射、HQL查询字符串和数据库的。如果需要的话,我也可以访问数据库 现在,我如何找出Hibernate可以从HQL生成的所有SQL查询,而不实际对任何数据库执行查询?这有什么工具吗 请注意,可以从一个HQL查询生成多个SQL查询,并且生成的SQL查询集可能会根据数据库的内容而有所不同 我不是问在HQL

我想“干运行”Hibernate HQL查询。也就是说,我想知道Hibernate将从给定的HQL查询执行什么样的实际SQL查询,而不实际对实际数据库执行HQL查询

我可以访问表的hibernate映射、HQL查询字符串和数据库的。如果需要的话,我也可以访问数据库

现在,我如何找出Hibernate可以从HQL生成的所有SQL查询,而不实际对任何数据库执行查询?这有什么工具吗

请注意,可以从一个HQL查询生成多个SQL查询,并且生成的SQL查询集可能会根据数据库的内容而有所不同

我不是问在HQL查询执行时如何记录SQL查询

编辑:我不介意连接到数据库获取一些元数据,我只是不想执行查询

编辑:我也知道什么限制和偏移应用于查询。我还有将绑定到查询的实际参数。

简短的回答是“你不能”。答案如下

您可以采取两种方法:

A) 调查,特别是它的。它不会为您提供精确的SQL,因为在实际执行查询之前需要进行进一步的预处理(绑定参数、应用限制/偏移量等),但它可能与您想要的足够接近

这里需要记住的是,为了构造
HQLQueryPlan
,您将需要一个实际的
SessionFactory
实例,这意味着如果不“连接到任何数据库”,您将无法这样做。但是,您可以使用内存中的数据库(SqlLite等),并让Hibernate自动为其创建必要的模式


B) 从AST/ANTLR疯狂开始并下降到AST/ANTLR疯狂。从理论上讲,您可能能够拼凑出一个解析器,它可以在不依赖元数据的情况下工作,但我很难想象,为了让它物有所值,您正在尝试做什么。也许你可以澄清一下?有一个更好的方法。

更新:对于一些HQL的离线试运行,直接使用HQLQueryPlan是一个好方法。如果您想在应用程序运行时拦截应用程序中的每个查询并记录SQL,则必须使用代理和反射,如下所述

看一看条件查询

对于HQL,这是相同的概念-您必须强制转换到Hibernate实现类和/或访问私有成员,因此它不是一个受支持的方法,但它将与Hibernate的3.2-3.3版本一起工作。以下是从HQL访问查询的代码(查询是session.createQuery(HQL\U字符串)返回的对象):

Field f=AbstractQueryImpl.class.getDeclaredField(“会话”);
f、 setAccessible(true);
SessionImpl SessionImpl=(SessionImpl)f.get(查询);
方法m=AbstractSessionImpl.class.getDeclaredMethod(“getHQLQueryPlan”,新类[]{String.class,boolean.class});
m、 setAccessible(true);
HQLQueryPlan=(HQLQueryPlan)m.invoke(sessionImpl,新对象[]{query.getQueryString(),Boolean.FALSE});
对于(int i=0;i
我会用try/catch来包装所有这些内容,以便在日志记录不起作用时继续查询


可以代理您的会话,然后代理您的查询,这样您就可以在每个查询(hql、sql、criteria)运行之前记录sql和参数,而无需构建查询的代码执行任何操作(只要从您控制的代码检索初始会话).

所有这些混淆视听的做法都是完全没有必要的。
HQLQueryPlan
有一个公共构造函数;您只需将会话工厂强制转换为
SessionFactoryImplementor
。没错,在重新阅读他的问题后,这可能就是他所需要的。我正在解决的问题是,您希望捕获HQL/SQL f或者应用程序中实时运行的每个查询—无需更改应用程序中执行查询的每个类。由于我没有删除功能,因此我添加了一行代码来澄清。这很公平;不过,如果您只想捕获SQL,则可能更容易(并且更可能在Hibernate更新后生存)要编写一个简单的appender并将其附加到
org.hibernate.SQL
:-),请同意。我让我的约束给我的解决方案涂上颜色,这些问题没有这些约束。我需要在sql运行时查看它,在数据库中保存计时,捕获参数和结果计数,用相同的参数对同一查询的多个执行进行分组,等等。对于这个问题,这些都是多余的。
Field f = AbstractQueryImpl.class.getDeclaredField("session");
f.setAccessible(true);
SessionImpl sessionImpl = (SessionImpl) f.get(query);
Method m = AbstractSessionImpl.class.getDeclaredMethod("getHQLQueryPlan", new Class[] { String.class, boolean.class });
m.setAccessible(true);
HQLQueryPlan plan = (HQLQueryPlan) m.invoke(sessionImpl, new Object[] { query.getQueryString(), Boolean.FALSE });
for (int i = 0; i < plan.getSqlStrings().length; ++i) {
  sql += plan.getSqlStrings()[i];
}