使用Hibernate时,如何打印带有参数值的查询字符串

在Hibernate中是否有可能用真实值而不是问号打印生成的SQL查询?

如果无法使用Hibernate API,您会建议如何使用实际值打印查询?

493687 次浏览

打开org.hibernate.type记录器,查看实际参数是如何绑定到问号的。

你需要为以下类别启用日志记录:

  • org.hibernate.SQL   -设置为debug,记录执行的所有SQL DML语句
  • org.hibernate.type -设置为trace记录所有JDBC参数

所以log4j配置可以是这样的:

# logs the SQL statements
log4j.logger.org.hibernate.SQL=debug


# Logs the JDBC parameters passed to a query
log4j.logger.org.hibernate.type=trace

第一个等价于hibernate.show_sql=true遗留财产,第二个等价于打印绑定参数。

另一个解决方案(非基于hibernate)是使用像P6Spy这样的JDBC代理驱动程序。

如果您正在使用hibernate 3.2。X使用这个:

log4j.logger.org.hibernate.SQL=trace

而不是这样:

log4j.logger.org.hibernate.SQL=debug

解决方案是正确的,但也记录结果对象的所有绑定。为了防止这种情况,可以创建一个单独的追加器并启用过滤。例如:

<!-- A time/date based rolling appender -->
<appender name="FILE_HIBERNATE" class="org.jboss.logging.appender.DailyRollingFileAppender">
<errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler"/>
<param name="File" value="${jboss.server.log.dir}/hiber.log"/>
<param name="Append" value="false"/>
<param name="Threshold" value="TRACE"/>
<!-- Rollover at midnight each day -->
<param name="DatePattern" value="'.'yyyy-MM-dd"/>


<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Message\n -->
<param name="ConversionPattern" value="%d %-5p [%c] %m%n"/>
</layout>
  

<filter class="org.apache.log4j.varia.StringMatchFilter">
<param name="StringToMatch" value="bind" />
<param name="AcceptOnMatch" value="true" />
</filter>
<filter class="org.apache.log4j.varia.StringMatchFilter">
<param name="StringToMatch" value="select" />
<param name="AcceptOnMatch" value="true" />
</filter>
<filter class="org.apache.log4j.varia.DenyAllFilter"/>
</appender>


<category name="org.hibernate.type">
<priority value="TRACE"/>
</category>


<logger name="org.hibernate.type">
<level value="TRACE"/>
<appender-ref ref="FILE_HIBERNATE"/>
</logger>


<logger name="org.hibernate.SQL">
<level value="TRACE"/>
<appender-ref ref="FILE_HIBERNATE"/>
</logger>

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

您可以在log4j.xml中添加类别行:

<category name="org.hibernate.type">
<priority value="TRACE"/>
</category>

并添加hibernate属性:

<property name="show_sql">true</property>
<property name="format_sql">true</property>
<property name="use_sql_comments">true</property>

为了方便起见,下面是Logback (SLF4J)的相同配置示例

<appender name="SQLROLLINGFILE">
<File>/tmp/sql.log</File>
<rollingPolicy>
<FileNamePattern>logFile.%d{yyyy-MM-dd}.log</FileNamePattern>
</rollingPolicy>
<layout>
<Pattern>%-4date | %msg %n</Pattern>
</layout>
</appender>


<logger name="org.hibernate.SQL" additivity="false" >
<level value="DEBUG" />
<appender-ref ref="SQLROLLINGFILE" />
</logger>


<logger name="org.hibernate.type" additivity="false" >
<level value="TRACE" />
<appender-ref ref="SQLROLLINGFILE" />
</logger>

sql.log(示例)中的输出如下所示:

2013-08-30 18:01:15,083 | update stepprovider set created_at=?, lastupdated_at=?, version=?, bundlelocation=?, category_id=?, customer_id=?, description=?, icon_file_id=?, name=?, shareStatus=?, spversion=?, status=?, title=?, type=?, num_used=? where id=?
2013-08-30 18:01:15,084 | binding parameter [1] as [TIMESTAMP] - 2012-07-11 09:57:32.0
2013-08-30 18:01:15,085 | binding parameter [2] as [TIMESTAMP] - Fri Aug 30 18:01:15 CEST 2013
2013-08-30 18:01:15,086 | binding parameter [3] as [INTEGER] -
2013-08-30 18:01:15,086 | binding parameter [4] as [VARCHAR] - com.mypackage.foo
2013-08-30 18:01:15,087 | binding parameter [5] as [VARCHAR] -
2013-08-30 18:01:15,087 | binding parameter [6] as [VARCHAR] -
2013-08-30 18:01:15,087 | binding parameter [7] as [VARCHAR] - TODO
2013-08-30 18:01:15,087 | binding parameter [8] as [VARCHAR] -
2013-08-30 18:01:15,088 | binding parameter [9] as [VARCHAR] - MatchingStep@com.mypackage.foo
2013-08-30 18:01:15,088 | binding parameter [10] as [VARCHAR] - PRIVATE
2013-08-30 18:01:15,088 | binding parameter [11] as [VARCHAR] - 1.0
2013-08-30 18:01:15,088 | binding parameter [12] as [VARCHAR] - 32
2013-08-30 18:01:15,088 | binding parameter [13] as [VARCHAR] - MatchingStep
2013-08-30 18:01:15,089 | binding parameter [14] as [VARCHAR] -
2013-08-30 18:01:15,089 | binding parameter [15] as [INTEGER] - 0
2013-08-30 18:01:15,089 | binding parameter [16] as [VARCHAR] - 053c2e65-5d51-4c09-85f3-2281a1024f64

使用Wireshark或类似的东西:

上面提到的答案都不会正确地打印带参数的SQL,或者让它与它们一起工作是一件痛苦的事情。我通过使用WireShark来实现这一点,它捕获从应用程序发送到Oracle/MySQL等的所有SQL/命令。

Log4JDBC是一个很好的解决方案,它打印确切的 SQL到数据库的参数,而不是这里最流行的答案,它不这样做。这样做的一个主要便利之处在于,您可以直接将SQL复制到您的DB前端并原样执行它。

后者还输出查询结果的表格表示。

示例输出显示生成的SQL与参数一起到位的结果集表从查询:

5. insert into ENQUIRY_APPLICANT_DETAILS (ID, INCLUDED_IN_QUOTE, APPLICANT_ID, TERRITORY_ID, ENQUIRY_ID, ELIGIBLE_FOR_COVER) values (7, 1, 11, 1, 2, 0)


10 Oct 2013 16:21:22 4953 [main] INFO  jdbc.resultsettable  - |---|--------|--------|-----------|----------|---------|-------|
10 Oct 2013 16:21:22 4953 [main] INFO  jdbc.resultsettable  - |ID |CREATED |DELETED |CODESET_ID |NAME      |POSITION |PREFIX |
10 Oct 2013 16:21:22 4953 [main] INFO  jdbc.resultsettable  - |---|--------|--------|-----------|----------|---------|-------|
10 Oct 2013 16:21:22 4953 [main] INFO  jdbc.resultsettable  - |2  |null    |null    |1          |Country 2 |1        |60     |
10 Oct 2013 16:21:22 4953 [main] INFO  jdbc.resultsettable  - |---|--------|--------|-----------|----------|---------|-------|

更新2016

最近,我一直在使用SLF4j和logbacklog4jdbc-log4j2 (https://code.google.com/archive/p/log4jdbc-log4j2/)。我的设置所需的Maven依赖项如下:

<dependency>
<groupId>org.bgee.log4jdbc-log4j2</groupId>
<artifactId>log4jdbc-log4j2-jdbc4.1</artifactId>
<version>1.16</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>$logback.version}</version>
</dependency>

驱动程序和DB url如下所示:

database.driver.class=net.sf.log4jdbc.sql.jdbcapi.DriverSpy
database.url=jdbc:log4jdbc:hsqldb:mem:db_name #Hsql
#database.url=jdbc:log4jdbc:mysql://localhost:3306/db_name

我的logback.xml配置文件如下所示:它输出所有带有参数的SQL语句以及所有查询的结果集表。

<?xml version="1.0" encoding="UTF-8"?>
<configuration>


<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>


<logger name="jdbc.audit" level="ERROR" />
<logger name="jdbc.connection" level="ERROR" />
<logger name="jdbc.sqltiming" level="ERROR" />
<logger name="jdbc.resultset" level="ERROR" />
    

<!-- UNCOMMENT THE BELOW TO HIDE THE RESULT SET TABLE OUTPUT -->
<!--<logger name="jdbc.resultsettable" level="ERROR" /> -->


<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>

最后,我必须在类路径的根目录下创建一个名为log4jdbc.log4j2.properties的文件,例如:在Maven项目中,src/test/resources或src/main/resources。这个文件只有一行:

log4jdbc.spylogdelegator.name=net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator

以上将取决于您的日志库。更多信息请参见https://code.google.com/archive/p/log4jdbc-log4j2文档。

样例输出:

10:44:29.400 [main] DEBUG jdbc.sqlonly -  org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:70)
5. select memberrole0_.member_id as member_i2_12_0_, memberrole0_.id as id1_12_0_, memberrole0_.id
as id1_12_1_, memberrole0_.member_id as member_i2_12_1_, memberrole0_.role_id as role_id3_12_1_,
role1_.id as id1_17_2_, role1_.name as name2_17_2_ from member_roles memberrole0_ left outer
join roles role1_ on memberrole0_.role_id=role1_.id where memberrole0_.member_id=104


10:44:29.402 [main] INFO  jdbc.resultsettable -
|----------|---|---|----------|--------|---|-----|
|member_id |id |id |member_id |role_id |id |name |
|----------|---|---|----------|--------|---|-----|
|----------|---|---|----------|--------|---|-----|

我喜欢log4j:

log4j.logger.org.hibernate.SQL=trace
log4j.logger.org.hibernate.engine.query=trace
log4j.logger.org.hibernate.type=trace
log4j.logger.org.hibernate.jdbc=trace
log4j.logger.org.hibernate.type.descriptor.sql.BasicExtractor=error
log4j.logger.org.hibernate.type.CollectionType=error

你可以记录这个:net.sf.hibernate.hql.QueryTranslator

输出的例子:

2013-10-31 14:56:19,029 DEBUG [net.sf.hibernate.hql.QueryTranslator] HQL: select noti.id, noti.idmicrosite, noti.fcaducidad, noti.fpublicacion, noti.tipo, noti.imagen, noti.visible, trad.titulo, trad.subtitulo, trad.laurl, trad.urlnom, trad.fuente, trad.texto  from org.ibit.rol.sac.micromodel.Noticia noti join noti.traducciones trad where index(trad)='ca' and noti.visible='S' and noti.idmicrosite=985 and noti.tipo=3446
2013-10-31 14:56:19,029 DEBUG [net.sf.hibernate.hql.QueryTranslator] SQL: select noticia0_.NOT_CODI as x0_0_, noticia0_.NOT_MICCOD as x1_0_, noticia0_.NOT_CADUCA as x2_0_, noticia0_.NOT_PUBLIC as x3_0_, noticia0_.NOT_TIPO as x4_0_, noticia0_.NOT_IMAGEN as x5_0_, noticia0_.NOT_VISIB as x6_0_, traduccion1_.NID_TITULO as x7_0_, traduccion1_.NID_SUBTIT as x8_0_, traduccion1_.NID_URL as x9_0_, traduccion1_.NID_URLNOM as x10_0_, traduccion1_.NID_FUENTE as x11_0_, traduccion1_.NID_TEXTO as x12_0_ from GUS_NOTICS noticia0_ inner join GUS_NOTIDI traduccion1_ on noticia0_.NOT_CODI=traduccion1_.NID_NOTCOD where (traduccion1_.NID_CODIDI='ca' )and(noticia0_.NOT_VISIB='S' )and(noticia0_.NOT_MICCOD=985 )and(noticia0_.NOT_TIPO=3446 )

将以下内容添加到log4j或logback配置中:

org.hibernate.sql=DEBUG
org.hibernate.type.descriptor.sql.BasicBinder=TRACE

你可以使用datasource-proxy,正如我在这篇文章中描述的那样。

假设你的应用程序需要一个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]}

datasource-proxy查询包含参数值,你甚至可以添加自定义JDBC语句拦截器,这样你就可以从集成测试中捕获N+1个查询问题

Log4Jdbc插件最适合您的需求。它显示如下-

1. Complete SQL query being hit to the db
2. Parameter values being passed to the query
3. Execution time taken by each query

参考下面的链接来配置Log4Jdbc-

https://code.google.com/p/log4jdbc/

如果你想让Hibernate用真实值而不是问号打印生成的SQL查询,向hibernate.cfg.xml/hibernate.properties添加以下条目:

show_sql=true
format_sql=true
use_sql_comments=true

并在log4j.properties中添加以下条目:

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

日志记录工作,但不完全是你想要的,我在一段时间前想要的,但P6Spy工作完美的

在这里也是一个简单的教程。对我来说,这就像魅力。

  1. 下载P6Spy库:获取p6spy-install.jar
  2. 提取:提取p6spy-install.jar文件,查找p6spy.jarspy.properties
  3. p6spy.jar添加到你的项目库依赖项中
  4. 修改P6Spy属性文件:修改数据库配置文件。你需要用P6Spy JDBC驱动程序替换现有的JDBC驱动程序(com.p6spy.engine.spy.P6SpyDriver)

原来是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>
  1. 修改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
  1. 拷贝spy.properties到你的项目根文件夹。确保你的项目可以找到spy.properties,否则会抛出spy.properties file not found异常。

<!-- A time/date based rolling appender -->
<appender name="FILE" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="logs/system.log" />
<param name="Append" value="true" />
<param name="ImmediateFlush" value="true" />
<param name="MaxFileSize" value="200MB" />
<param name="MaxBackupIndex" value="100" />


<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %d{Z} [%t] %-5p (%F:%L) - %m%n" />
</layout>
</appender>


<appender name="journaldev-hibernate" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="logs/project.log" />
<param name="Append" value="true" />
<param name="ImmediateFlush" value="true" />
<param name="MaxFileSize" value="200MB" />
<param name="MaxBackupIndex" value="50" />


<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %d{Z} [%t] %-5p (%F:%L) - %m%n" />
</layout>
</appender>


<logger name="com.journaldev.hibernate" additivity="false">
<level value="DEBUG" />
<appender-ref ref="journaldev-hibernate" />
</logger>


<logger name="org.hibernate" additivity="false">
<level value="INFO" />
<appender-ref ref="FILE" />
</logger>


<logger name="org.hibernate.type" additivity="false">
<level value="TRACE" />
<appender-ref ref="FILE" />
</logger>


<root>
<priority value="INFO"></priority>
<appender-ref ref="FILE" />
</root>

<appender name="console" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n" />
</layout>
</appender>


<logger name="org.hibernate" additivity="false">
<level value="INFO" />
<appender-ref ref="console" />
</logger>


<logger name="org.hibernate.type" additivity="false">
<level value="TRACE" />
<appender-ref ref="console" />
</logger>

使用Hibernate 4和slf4j/log4j2,我尝试在我的log4j2.xml配置中添加以下内容:

<Logger name="org.hibernate.type.descriptor.sql.BasicBinder" level="trace" additivity="false">
<AppenderRef ref="Console"/>
</Logger>
<Logger name="org.hibernate.type.EnumType" level="trace" additivity="false">
<AppenderRef ref="Console"/>
</Logger>

但是没有成功。

我通过这个线程发现Hibernate使用的jboss-logging框架需要配置,以便通过slf4j进行日志记录。我将以下参数添加到应用程序的VM参数中:

-Dorg.jboss.logging.provider=slf4j

而且效果很好。

这个答案对这个问题有点不同。 有时,我们只需要sql在运行时进行调试。 在这种情况下,有一个更简单的方法,在编辑器上使用调试
  • org.hibernate.loader.Loader.loadEntityBatch上放置一个断点(或在堆栈上导航到那里);
  • 当执行暂停时,查看变量this.sql的值

这是针对Hibernate 3的。我不确定这是否适用于其他版本。

这里的所有答案都很有帮助,但是如果您使用Spring应用程序上下文XML来设置会话工厂,那么设置log4j SQL级别变量只是完成了一部分工作,您还必须设置hibernate。show_sql变量在应用程序上下文中本身来让Hibernate开始实际显示这些值。

中有:

<property name="hibernateProperties">
<value>
hibernate.jdbc.batch_size=25
... <!-- Other parameter values here -->
hibernate.show_sql=true
</value>
</property>

您的log4j文件需要

log4j.logger.org.hibernate.SQL=DEBUG

如果你正在使用Spring Boot,只需配置如下:

application.yml

logging:
level:
org.hibernate.SQL: DEBUG
org.hibernate.type: TRACE

application.properties

logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type=TRACE

仅此而已。

你的日志会是这样的:

2020-12-07 | DEBUG | o.h.SQL:127 - insert into Employee (id, name, title, id) values (?, ?, ?, ?)
2020-12-07 | TRACE | o.h.t.d.s.BasicBinder:64 - binding parameter [1] as [VARCHAR] - [001]
2020-12-07 | TRACE | o.h.t.d.s.BasicBinder:64 - binding parameter [2] as [VARCHAR] - [John Smith]
2020-12-07 | TRACE | o.h.t.d.s.BasicBinder:52 - binding parameter [3] as [VARCHAR] - [null]
2020-12-07 | TRACE | o.h.t.d.s.BasicBinder:64 - binding parameter [4] as [BIGINT] - [1]

MySQL JDBC驱动程序已经提供了一个方便的特性来满足这个需求。您必须至少拥有大于或等于5.1.6的JAR版本(例如mysql-connect-jar-5.1.6.jar)

  1. 配置jdbc.url来添加记录器您的记录器和自定义日志:
    jdbc.url=jdbc:mysql://host:port/your_db?logger=com.mysql.jdbc.log.Slf4JLogger&profileSQL=true&profilerEventHandler=com.xxx.CustomLoggingProfilerEventHandler
    

它使用slf4j日志记录,如果你的默认日志记录是log4j,你必须添加slf4j-apislf4j-log4j12作为依赖项来使用slf4j日志记录:

  1. 编写自定义日志代码:

    package com.xxx;
    import java.sql.SQLException;
    import java.util.Properties;
    
    
    import com.mysql.jdbc.Connection;
    import com.mysql.jdbc.log.Log;
    
    
    public class CustomLoggingProfilerEventHandler implements ProfilerEventHandler {
    private Log log;
    
    
    public LoggingProfilerEventHandler() {
    }
    
    
    public void consumeEvent(ProfilerEvent evt) {
    /**
    * you can only print the sql as his.log.logInfo(evt.getMessage())
    * you can adjust your sql print log level with: DEBUG,INFO
    * you can also handle the message to meet your requirement
    */
    this.log.logInfo(evt);
    }
    
    
    public void destroy() {
    this.log = null;
    }
    
    
    public void init(Connection conn, Properties props) throws SQLException {
    this.log = conn.getLog();
    }
    }
    

下面是对我有用的,在log4j.file中设置下面的属性:

log4j.logger.org.hibernate.type.descriptor.sql.BasicBinder=TRACE

Hibernate属性设置:

hibernate.show_sql=true

在Java中:

如果查询是CriteriaQuery (javax.persistence),则转换TypedQuery中的查询。

然后:

query.unwrap (org.hibernate.Query.class) .getQueryString ();

Hibernate在不同的行中显示查询及其参数值。

如果你在Spring Boot中使用application.properties,你可以在application.properties中使用下面突出显示的参数。

  • org.hibernate.SQL将显示查询:

    logging.level.org.hibernate.SQL=DEBUG
    
  • org.hibernate.type将显示所有参数值,这些值将映射到selectinsertupdate查询。

    logging.level.org.hibernate.type=TRACE
    
  • org.hibernate.type.EnumType将显示enum类型参数值:

    logging.level.org.hibernate.type.EnumType=TRACE
    

    示例输出:

    2018-06-14 11:06:28,217 TRACE [main] [EnumType.java : 321] Binding [active] to parameter: [1]
    
  • sql.BasicBinder将显示整数,varchar,布尔类型参数值

    logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
    

    示例输出:

    * 2018-06-14 11:28:29,750 TRACE [http-nio-9891-exec-2] [BasicBinder.java : 65] binding parameter [1] as [BOOLEAN] - [true]
    * 2018-06-14 11:28:29,751 TRACE [http-nio-9891-exec-2] [BasicBinder.java : 65] binding parameter [2] as [INTEGER] - [1]
    * 2018-06-14 11:28:29,752 TRACE [http-nio-9891-exec-2] [BasicBinder.java : 65] binding parameter [3] as [VARCHAR] - [public]
    

对我来说,最简单的解决方案是实现一个常规的字符串替换,将参数输入替换为参数值(为了简单起见,将所有参数都视为字符串):

String debuggedSql = sql;
// then, for each named parameter
debuggedSql = debuggedSql.replaceAll(":"+key, "'"+value.toString()+"'");
// and finally
System.out.println(debuggedSql);

或者类似的位置参数(?)。

如果您想要记录运行就绪的SQL,请注意空值和特定的值类型(如date)。

在使用Wildfly (standalone.xml)进行开发时,添加以下记录器:

<logger category="org.hibernate.SQL">
<level name="DEBUG"/>
</logger>
<logger category="org.hibernate.type.descriptor.sql">
<level name="TRACE"/>
</logger>

使用YAML属性:

logging.level.org.hibernate:
SQL: DEBUG
type.descriptor.sql.BasicBinder: TRACE

这里所有的答案我都有问题。它们实际上都没有为Spring Data JPA查询提供参数,该查询正在作为PK传递枚举。

对于Hibernate 5.3:

    <!-- silence the noise -->
<Logger name="org.hibernate.search.engine.metadata.impl" additivity="false"/>
<Logger name="org.hibernate.boot.internal" additivity="false"/>
<Logger name="org.hibernate.engine.internal" additivity="false"/>
<Logger name="org.hibernate.engine.jdbc" additivity="false"/>
<Logger name="org.hibernate.engine.transaction" additivity="false"/>
<Logger name="org.hibernate.engine.loading.internal" additivity="false"/>
<Logger name="org.hibernate.engine.spi.CollectionEntry" additivity="false"/>
<Logger name="org.hibernate.engine.query.spi.HQLQueryPlan" additivity="false"/>
<Logger name="org.hibernate.engine.query.spi.QueryPlanCache" additivity="false"/>
<Logger name="org.hibernate.engine.spi.IdentifierValue" additivity="false"/>
<Logger name="org.hibernate.engine.spi.CascadingActions" additivity="false"/>
<Logger name="org.hibernate.engine.spi.ActionQueue" additivity="false"/>
<Logger name="org.jboss.logging"/>
    

<Logger name="org.hibernate.SQL" level="debug" additivity="false">
<AppenderRef ref="Console"/>
</Logger>
<Logger name="org.hibernate.type.descriptor.sql.BasicBinder" level="trace" additivity="false">
<AppenderRef ref="Console"/>
</Logger>
<Logger name="org.hibernate.engine" level="trace" additivity="false">
<AppenderRef ref="Console"/>
</Logger>

为了更好地打印,将hibernate.format_sql设置为true,这是我的输出示例:

17:00:00,664 [TRACE] Named parameters: {1=DE} [main] org.hibernate.engine.spi.QueryParameters.traceParameters(QueryParameters.java:325)
17:00:00,671 [DEBUG]
select
countrysub0_.code as code1_23_,
countrysub0_1_.country_subdivision as country_1_61_
from
country_subdivision countrysub0_
left outer join
jurisdiction_country_subdivision countrysub0_1_
on countrysub0_.code=countrysub0_1_.jurisdiction
where
countrysub0_.code=? [main] org.hibernate.engine.jdbc.spi.SqlStatementLogger.logStatement(SqlStatementLogger.java:103)

我尝试简单地将org.hibernate.engine.spi.QueryParameters设置为trace,但由于某种原因,命名参数一直被禁用,所以我禁用了所有其他正在记录日志的参数。它似乎没有记录所有参数,所以我仍然需要BasicBinding日志。

您需要配置如下:

# Hibernate logging options (INFO only shows startup messages)
log4j.logger.org.hibernate=INFO


# Log JDBC bind parameter runtime arguments
log4j.logger.org.hibernate.type=trace

如果您正在使用spring-boot,您可以使用log4jdbc-spring-boot-starter依赖项,它是org.bgee的一个分支。log4jdbc-log4j2。

pom.xml中,我使用了以下依赖项:

   <dependency>
<groupId>com.integralblue</groupId>
<artifactId>log4jdbc-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>

在文档中提到,如果只包含这个依赖项,SQL日志记录将不起作用,我们必须在application.properties中指定以下属性

logging.level.jdbc.sqlonly=INFO

但随着

2.0.0版本,所有日志属性默认设置为info。在撰写本文时,2.0.0的使用计数比1.0.2要少

因此,在2.0.0中,即使您不指定任何用于记录sql的属性,下面的属性也是默认设置的

logging.level.jdbc.sqlonly=INFO
logging.level.jdbc.resultset=INFO
logging.level.jdbc.connection=INFO
logging.level.jdbc.resultsettable=INFO
logging.level.jdbc.audit=INFO
logging.level.jdbc.sqltiming=INFO

如果你只想打印SQL查询?替换为实际值,避免不必要的日志从结果集这些属性显式到

logging.level.jdbc.sqlonly=INFO
logging.level.jdbc.resultset=OFF
logging.level.jdbc.connection=OFF
logging.level.jdbc.resultsettable=OFF
logging.level.jdbc.audit=OFF
logging.level.jdbc.sqltiming=OFF

如果您使用Spring Boot 3和/或Hibernate 6,以下配置将显示参数值:

# basic log level for all messages
logging.level.org.hibernate=info
# SQL statements and parameters
logging.level.org.hibernate.SQL=debug
logging.level.org.hibernate.orm.jdbc.bind=trace
# Statistics and slow queries
logging.level.org.hibernate.stat=debug
logging.level.org.hibernate.SQL_SLOW=info
# 2nd Level Cache
logging.level.org.hibernate.cache=debug