在Hibernate中是否有可能用真实值而不是问号打印生成的SQL查询?
如果无法使用Hibernate API,您会建议如何使用实际值打印查询?
在Hibernate中是否有可能用真实值而不是问号打印生成的SQL查询?
如果无法使用Hibernate API,您会建议如何使用实际值打印查询?
当前回答
在Java中:
如果查询是CriteriaQuery (javax.persistence),则转换TypedQuery中的查询。
然后:
query.unwrap (org.hibernate.Query.class) .getQueryString ();
其他回答
日志可以工作,但并不是您想要的,但P6Spy可以完美地工作。
这里有一个简单的教程来实现以及。对我来说,这就像魅力。
下载P6Spy库:获取P6Spy -install.jar 解压:解压p6spy-install.jar文件,查找p6spy.jar和spy.properties 添加库依赖项:将p6spy.jar添加到项目库依赖项中 Modify P6Spy properties file:修改数据库配置文件。您需要用P6Spy JDBC驱动程序替换现有的JDBC驱动程序。
原来是MySQL JDBC驱动程序- (com.mysql.jdbc.Driver)
<session-factory>
<property name="hibernate.bytecode.use_reflection_optimizer">false</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <!-- note the difference -->
<property name="hibernate.connection.password">password</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/myuser</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="show_sql">true</property>
</session-factory>
更改为P6Spy JDBC驱动程序(com.p6spy.engine.spy.P6SpyDriver)
<session-factory>
<property name="hibernate.bytecode.use_reflection_optimizer">false</property>
<property name="hibernate.connection.driver_class">com.p6spy.engine.spy.P6SpyDriver</property> <!-- note the difference -->
<property name="hibernate.connection.password">password</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/myuser</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="show_sql">true</property>
</session-factory>
修改P6Spy属性文件:spy.properties
用现有的MySQL JDBC驱动程序替换realdriver
realdriver=com.mysql.jdbc.Driver
# specifies another driver to use
realdriver2=
# specifies a third driver to use
realdriver3=
在logfile属性中更改日志文件的位置。所有SQL语句都将被记录到这个文件中。
窗口:
logfile=c:/spy.log
UNIX:
logfile=/srv/log/spy.log
复制的间谍。属性到项目类路径:复制间谍。属性添加到项目根文件夹。确保你的项目可以定位间谍。财产,否则就是间谍。属性文件未找到异常将被抛出。
正如我在这篇文章中所描述的,您可以使用数据源-代理来实现。
假设你的应用程序需要一个dataSource bean(例如通过@Resource),你可以这样配置dataSource -proxy:
<bean id="actualDataSource" class="bitronix.tm.resource.jdbc.PoolingDataSource" init-method="init"
destroy-method="close">
<property name="className" value="bitronix.tm.resource.jdbc.lrc.LrcXADataSource"/>
<property name="uniqueName" value="actualDataSource"/>
<property name="minPoolSize" value="0"/>
<property name="maxPoolSize" value="5"/>
<property name="allowLocalTransactions" value="false" />
<property name="driverProperties">
<props>
<prop key="user">${jdbc.username}</prop>
<prop key="password">${jdbc.password}</prop>
<prop key="url">${jdbc.url}</prop>
<prop key="driverClassName">${jdbc.driverClassName}</prop>
</props>
</property>
</bean>
<bean id="proxyDataSource" class="net.ttddyy.dsproxy.support.ProxyDataSource">
<property name="dataSource" ref="testDataSource"/>
<property name="listener">
<bean class="net.ttddyy.dsproxy.listener.ChainListener">
<property name="listeners">
<list>
<bean class="net.ttddyy.dsproxy.listener.CommonsQueryLoggingListener">
<property name="logLevel" value="INFO"/>
</bean>
<bean class="net.ttddyy.dsproxy.listener.DataSourceQueryCountListener"/>
</list>
</property>
</bean>
</property>
</bean>
<alias name="proxyDataSource" alias="dataSource"/>
现在Hibernate输出vs.数据源-代理:
INFO [main]: n.t.d.l.CommonsQueryLoggingListener - Name:, Time:1, Num:1, Query:{[select company0_.id as id1_6_, company0_.name as name2_6_ from Company company0_][]}
INFO [main]: n.t.d.l.CommonsQueryLoggingListener - Name:, Time:0, Num:1, Query:{[insert into WarehouseProductInfo (id, quantity) values (default, ?)][19]}
INFO [main]: n.t.d.l.CommonsQueryLoggingListener - Name:, Time:0, Num:1, Query:{[insert into Product (id, code, company_id, importer_id, name, version) values (default, ?, ?, ?, ?, ?)][phoneCode,1,-5,Phone,0]}
数据源-代理查询包含参数值,您甚至可以添加自定义JDBC语句拦截器,以便从集成测试中捕获N+1个查询问题。
对我来说,最简单的解决方案是实现一个常规的字符串替换,将参数输入替换为参数值(为了简单起见,将所有参数都视为字符串):
String debuggedSql = sql;
// then, for each named parameter
debuggedSql = debuggedSql.replaceAll(":"+key, "'"+value.toString()+"'");
// and finally
System.out.println(debuggedSql);
或者类似的位置参数(?)。
如果您想要记录运行就绪的SQL,请注意空值和特定的值类型(如date)。
将hibernate.cfg.xml修改为:
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<property name="use_sql_comments">true</property>
在"log4j.properties"中包含log4j和以下条目:
log4j.logger.org.hibernate=INFO, hb
log4j.logger.org.hibernate.SQL=DEBUG
log4j.logger.org.hibernate.type=TRACE
log4j.appender.hb=org.apache.log4j.ConsoleAppender
log4j.appender.hb.layout=org.apache.log4j.PatternLayout
这个答案对这个问题有点不同。 有时,我们只需要sql在运行时进行调试。 在这种情况下,有一种更简单的方法,在编辑器上使用调试。
在org.hibernate.loader.Loader.loadEntityBatch上放置一个断点(或在堆栈上导航到那里); 当执行暂停时,查看变量this.sql的值
这是针对Hibernate 3的。我不确定这是否适用于其他版本。