【问题标题】:How to print a query string with parameter values when using Hibernate使用 Hibernate 时如何打印带有参数值的查询字符串
【发布时间】:2010-12-15 04:37:15
【问题描述】:

是否可以在 Hibernate 中使用实际值而不是问号打印生成的 SQL 查询?

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

【问题讨论】:

标签: java sql hibernate orm


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    您需要为以下类别启用logging

    • 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 legacy property,第二个打印绑定的参数等。

    另一种解决方案(不基于休眠)是使用 JDBC 代理驱动程序,如 P6Spy

    【讨论】:

    • 这很有用。但这并没有向我展示真正的 SQL 查询。
    • @Nicolas 没错,但是在查询之后它立即显示绑定的参数。
    • 我正在使用 grails 2.4.4 和 hibernate 4。更改 log4j 配置对我不起作用,但 p6spy 有效!
    • 在 Hibernate 5 中,我们可以使用 org.hibernate.type.descriptor.sql.BasicBinder 记录器。启用登录org.hibernate.type 为我打印了太多无用的信息...
    • org.hibernate.typeorg.hibernate.loader.hql 不适合我显示参数
    【解决方案3】:

    如果您使用的是 hibernate 3.2.X,请使用:

    log4j.logger.org.hibernate.SQL=trace
    

    而不是这个:

    log4j.logger.org.hibernate.SQL=debug 
    

    【讨论】:

      【解决方案4】:

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

      <!-- 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>
      

      【讨论】:

        【解决方案5】:

        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 查询下添加binding parameter [1] as [VARCHAR] - [1] 之类的参数。
        【解决方案6】:

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

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

        并添加休眠属性:

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

        【讨论】:

          【解决方案7】:

          为方便起见,这里是 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
          

          【讨论】:

          • 这不是回答 OP 的问题。
          【解决方案8】:

          使用Wireshark 或类似的东西:

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

          【讨论】:

          • Log4JDBC 会。见上文。
          【解决方案9】:

          Log4JDBC 是一个很好的解决方案,它打印 exact SQL 并使用适当的参数进入数据库,而不是这里最流行的答案,它没有这样做。这样做的一个主要便利是您可以将 SQL 直接复制到数据库前端并按原样执行。

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

          显示生成的 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 年更新

          最近我一直在使用 log4jdbc-log4j2 (https://code.google.com/archive/p/log4jdbc-log4j2/ ) 与 SLF4j 和 logback。我的设置所需的 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>
          

          驱动程序和数据库 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 的文件,例如src/test/resources 或 src/main/resources 在 Maven 项目中。这个文件只有一行:

          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 |
          |----------|---|---|----------|--------|---|-----|
          |----------|---|---|----------|--------|---|-----|
          

          【讨论】:

          • 嘿......这看起来很酷......正是医生为我订购的:)......但它也支持 CLOB/BLOB 吗?此外,是否可以只显示查询而不显示结果集。 - 谢谢:)
          • 你能给我一个配置的例子吗?
          • 实际上,latter 输出查询结果的表格表示形式......即,需要 log4jdbc-remix 来获得这个不错的功能。
          • 这个解决方案最适合我需要查看 Hibernate 为分页结果集生成的行号值的情况。跟踪日志只显示查询参数值。
          • @Alan Hay 这也记录本机查询吗?
          【解决方案10】:

          我喜欢 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 
          

          【讨论】:

          • 嘿 - 这很好。但我认为这里的查询是用 ?后跟参数值。由于我有无限多的查询,我需要一些我可以在 sql 编辑器上复制粘贴的东西,它们将被执行。有没有办法使用这种方法来做到这一点。我不太热衷于去第三方图书馆。谢谢:)
          • 谢谢。我希望不必使用任何 3rd 方解决方案并直接休眠,但我想我别无选择。
          【解决方案11】:

          您可以登录: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 )
          

          【讨论】:

          • 嘿...我找不到这种方法的任何例子。您能否提供任何参考/示例/教程。最新版本还是 hibernate/log4j 还是一样,还是变成了 org.hibernate.QueryTranslator 什么的。谢谢
          • 嘿...我试过了,但这似乎不适用于保存或更新。我猜它只适用于选择查询,从 hql 到 sql 的翻译发挥作用
          【解决方案12】:

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

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

          【讨论】:

          • org.hibernate.type.descriptor.sql.BasicBinder 类别不包括所有参数,例如枚举类型。因此,如果您想要一切,您真的需要为整个org.hibernate.type 组提供TRACE
          • 对我来说,它适用于 Hibernate 4.3!另外,我不会跟踪完整的 org.hibernate.type,因为输出太多了。在大多数情况下,此解决方案都可以。
          • 请注意 org.hibernate.type.descriptor.sql.BasicExtractor 记录结果集。因此,在 Eclipse 中登录到控制台时,拥有大尺寸条目甚至会导致应用程序崩溃,而且我想它也不适合登录到文件中。这就是为什么我更喜欢这个解决方案,它也适用于 Hibernate 3。对于那些对枚举类型感兴趣的人,请尝试在 org.hibernate.type=TRACE 时记录它们的确切类。然后设置 org.hibernate.type.xyz.TheClassThatLogsEnumParams=TRACE。
          【解决方案13】:

          您可以使用datasource-proxy 来完成,正如我在this post 中描述的那样。

          假设您的应用程序需要一个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 输出与数据源代理:

          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 语句拦截器,以便您可以catch N+1 query issues right from your integration tests

          【讨论】:

            【解决方案14】:

            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/
            

            【讨论】:

              【解决方案15】:

              如果您希望 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
              

              【讨论】:

              • Hey single31 上面的行必须添加到您的休眠配置文件中,然后它肯定会起作用。我总是发布我实际做过的事情。
              【解决方案16】:

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

              Here 也是实现的简单教程。对我来说,它就像魅力一样。

              1. 下载 P6Spy 库: 获取 p6spy-install.jar
              2. 解压:解压p6spy-install.jar文件,查找p6spy.jarspy.properties
              3. 添加库依赖:p6spy.jar添加到您的项目库依赖中
              4. 修改 P6Spy 属性文件: 修改您的数据库配置文件。您需要将现有的 JDBC 驱动程序替换为 P6Spy 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,否则将引发spy.properties file not found 异常。

              【讨论】:

              • 在我的 Spring Boot 应用程序中,这对我来说是最简单的路径,我试图记录从单元测试生成的 SQL。我向 Gradle 添加了一个测试依赖项(testCompile 'p6spy:p6spy:3.8.5'),调整了 application.yml 以设置 spring.datasource.url=jdbc:p6spy:h2:mem:testdb 和 spring.datasource.driver-class- name=com.p6spy.engine.spy.P6SpyDriver,然后添加 spy.properties 并将 realdriver=org.h2.Driver 和日志文件设置为我的首选路径。从生成的日志文件中提取完整的 SQL 很容易。唯一的问题是 H2 不喜欢生成的时间戳格式。
              【解决方案17】:

              <!-- 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>
              

              【讨论】:

                【解决方案18】:

                <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>
                

                【讨论】:

                • 这与问题有什么关系?
                【解决方案19】:

                使用 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>
                

                但没有成功。

                我通过this thread发现需要配置Hibernate使用的jboss-logging框架才能通过slf4j登录。我在应用程序的 VM 参数中添加了以下参数:

                -Dorg.jboss.logging.provider=slf4j
                

                它就像一个魅力。

                【讨论】:

                  【解决方案20】:

                  这个答案与这个问题有点不同。 有时,我们只需要 sql 仅用于运行时的调试目的。 在这种情况下,有一种更简单的方法,即在编辑器上使用调试。

                  • org.hibernate.loader.Loader.loadEntityBatch 上放置一个断点(或在堆栈上导航直到那里);
                  • 暂停执行时,查看变量this.sql的值

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

                  【讨论】:

                    【解决方案21】:

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

                    ApplicationContext.xml 有:

                    <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
                    

                    【讨论】:

                      【解决方案22】:

                      如果您使用的是 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]
                      

                      【讨论】:

                        【解决方案23】:

                        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();
                              }
                          }
                          

                        【讨论】:

                          【解决方案24】:

                          这对我有用,在 log4j.file 中设置以下属性:

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

                          休眠属性设置:

                          hibernate.show_sql=true
                          

                          【讨论】:

                            【解决方案25】:

                            在 Java 中:

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

                            然后:

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

                            【讨论】:

                            • 谢谢,它打印查询,但不打印它使用的参数,有办法打印参数吗?
                            • 很抱歉,我认为不可能像这样映射它们。我会记录它们并手动完成工作作为解决方法;)
                            【解决方案26】:

                            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 会显示枚举类型参数值:

                              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]
                              

                            【讨论】:

                            • 即使这样也不会在查询中显示 limitoffset 的值。
                            【解决方案27】:

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

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

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

                            如果您希望记录运行就绪的 SQL,请注意空值和特定值类型(如日期)。

                            【讨论】:

                              【解决方案28】:

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

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

                              【讨论】:

                                【解决方案29】:

                                hibernate-types 有一个实用方法来记录 JPQL 和条件查询。更多细节可以在作者的blog post 中找到。这是一个使用 JPQL 的示例:

                                Query jpql = entityManager.createQuery("""
                                    select
                                       YEAR(p.createdOn) as year,
                                       count(p) as postCount
                                    from
                                       Post p
                                    group by
                                       YEAR(p.createdOn)
                                    """, Tuple.class
                                );
                                String sql = SQLExtractor.from(jpql);
                                

                                sql 变量具有以下值:

                                SELECT
                                    extract(YEAR FROM sqlextract0_.created_on) AS col_0_0_,
                                    count(sqlextract0_.id) AS col_1_0_
                                FROM
                                    post p
                                GROUP BY
                                    extract(YEAR FROM p.created_on)
                                

                                它可以按原样复制粘贴到数据库控制台中。

                                【讨论】:

                                  【解决方案30】:

                                  使用 YAML 属性:

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

                                  【讨论】:

                                    猜你喜欢
                                    • 2014-12-01
                                    • 1970-01-01
                                    • 2021-09-24
                                    • 2011-04-23
                                    • 1970-01-01
                                    • 1970-01-01
                                    相关资源
                                    最近更新 更多