Como imprimir uma string de consulta com valores de parâmetro ao usar o Hibernate


Respostas:


428

Você precisa habilitar o log para as seguintes categorias:

  • org.hibernate.SQL   - definido como debugpara registrar todas as instruções SQL DML à medida que são executadas
  • org.hibernate.type- configure para traceregistrar todos os parâmetros JDBC

Portanto, uma configuração do log4j pode se parecer com:

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

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

O primeiro é equivalente à propriedadehibernate.show_sql=true herdada , o segundo imprime os parâmetros vinculados entre outras coisas.

Outra solução (não baseada em hibernação) seria usar um driver proxy JDBC como o P6Spy .


11
Isso é útil. Mas isso não me mostra as consultas SQL reais.
Nicolas Barbulesco

6
@ Nicolas isso é verdade, no entanto, imediatamente após a consulta, ele dispersa os parâmetros vinculados.
Xtreme Biker

2
Estou usando grails 2.4.4 e hibernate 4. Alterar a configuração do log4j não funcionou para mim, mas o p6spy funcionou!
Champ

11
No Hibernate 5, podemos usar o org.hibernate.type.descriptor.sql.BasicBinderlogger. A ativação do logon org.hibernate.typeimprimiu muitas informações inúteis para mim ...
csharpfolk

5
org.hibernate.typee org.hibernate.loader.hqlnão funciona para mim para mostrar os parâmetros
Dherik

75

Apenas por conveniência, aqui está o mesmo exemplo de configuração para 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>

A saída no seu sql.log (exemplo) fica assim:

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

2
Isso não está respondendo à pergunta dos OPs.
ShadowGames 15/10/19

33

Mude hibernate.cfg.xmlpara:

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

Inclua log4j e entradas abaixo em "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

Obrigado, funcionou muito bem para mim. Essas configurações adicionarão na consulta sql um parâmetro como binding parameter [1] as [VARCHAR] - [1].
G. Ciardini

28

No caso de inicialização por mola, apenas configure isso:

aplication.yml

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

aplication.properties

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

e nada mais.

HTH


20

O Log4JDBC é uma boa solução que imprime o SQL exato que vai para o banco de dados com parâmetros em vez da resposta mais popular aqui, que não faz isso. Uma grande conveniência disso é que você pode copiar o SQL diretamente para o front-end do banco de dados e executar como está.

http://log4jdbc.sourceforge.net/

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

O último também gera uma representação tabular dos resultados da consulta.

Saída de amostra mostrando o SQL gerado com parâmetros no lugar junto com a tabela do conjunto de resultados da consulta:

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

Atualização 2016

Mais recentemente, agora uso log4jdbc-log4j2 ( https://code.google.com/archive/p/log4jdbc-log4j2/ ) com SLF4j e logback. As dependências do Maven necessárias para minha configuração são as seguintes:

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

O driver e os URLs do banco de dados são parecidos com:

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 

Meu arquivo de configuração logback.xml é semelhante ao abaixo: isso gera todas as instruções SQL com parâmetros e as tabelas de conjunto de resultados para todas as consultas.

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

Finalmente, tive que criar um arquivo chamado log4jdbc.log4j2.properties na raiz do caminho de classe, por exemplo, src / test / resources ou src / main / resources em um projeto Mevn. Este arquivo tem uma linha que é a abaixo:

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

O acima dependerá da sua biblioteca de log. Veja os documentos em https://code.google.com/archive/p/log4jdbc-log4j2 para obter mais informações

Saída de amostra:

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

11
Ei .... Isso parece legal .... exatamente o que o médico pediu para mim :) ... mas também suporta CLOB / BLOB ?? Além disso, é possível exibir apenas a consulta e não o conjunto de resultados. - Obrigado :)
dev ray

11
você poderia me dar um exemplo de configuração como fazer isso?
grep

Na verdade, o último gera uma representação tabluar dos resultados da consulta ... ou seja, é preciso log4jdbc-remix para esse recurso interessante.
meriton

Essa solução foi melhor para minha situação em que eu precisava ver os valores do número da linha que o Hibernate gera para os conjuntos de resultados de paginação. O log de rastreamento mostra apenas os valores dos parâmetros de consulta.
Oliver Hernandez

@ Alan Hay também registra consultas nativas?
Sayantan 30/07/19

9

Você pode adicionar linhas de categoria ao log4j.xml:

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

e adicione propriedades de hibernação:

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

7

adicione as seguintes propriedades e valores à sua configuração log4j ou logback:

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

5
A org.hibernate.type.descriptor.sql.BasicBindercategoria não inclui todos os parâmetros, por exemplo, tipos de enumeração. Então, se você quer tudo, você realmente precisa TRACEpara todo o org.hibernate.typegrupo.
Seanf

Para mim, funciona no Hibernate 4.3! Além disso, eu não rastrearia o org.hibernate.type completo, porque isso é muita saída. Na maioria dos casos, esta solução serve.
cslotty

Observe que org.hibernate.type.descriptor.sql.BasicExtractor registra os conjuntos de resultados. Portanto, ter uma entrada de tamanho grande pode até travar a aplicação ao efetuar logon no console no Eclipse, e suponho que também não seja ideal para efetuar logon no arquivo. É por isso que prefiro esta solução, que também funciona no Hibernate 3. Para aqueles que estão interessados ​​em tipos de enumeração, tente a classe exata que os registra quando org.hibernate.type = TRACE. Em seguida, defina org.hibernate.type.xyz.TheClassThatLogsEnumParams = TRACE.
Géza

7

Você pode fazer isso usando o proxy da fonte de dados , como descrevi neste post .

Supondo que seu aplicativo espere um dataSourcebean (por exemplo, via @Resource), é assim que você pode configurar 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"/>

Agora a saída do Hibernate vs datasource-proxy:

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

As datasource-proxyconsultas contêm valores de parâmetro e você pode até adicionar interceptores de instruções JDBC customizados para detectar problemas de consulta N + 1 diretamente de seus testes de integração .


5

ligue o org.hibernate.typecriador de logs para ver como os parâmetros reais estão vinculados aos pontos de interrogação.


4

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


3

A solução está correta, mas também registra todas as ligações para os objetos de resultado. Para evitar isso, é possível criar um aplicativo separado e ativar a filtragem, por exemplo:

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

3
**If you want hibernate to print generated sql queries with real values instead of question marks.**
**add following entry in hibernate.cfg.xml/hibernate.properties:**
show_sql=true
format_sql=true
use_sql_comments=true

**And add following entry in 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 linhas acima tem que ser adicionado ao seu arquivo de configuração de hibernação, então ele definitivamente funcionará. Eu sempre posto coisas que praticamente fiz.
Vijay Bhatt

3

Esta resposta é uma pequena variação para a pergunta. Às vezes, precisamos apenas do sql apenas para fins de depuração em tempo de execução. Nesse caso, há uma maneira mais fácil, usando a depuração nos editores.

  • Coloque um ponto de interrupção em org.hibernate.loader.Loader.loadEntityBatch (ou navegue na pilha até lá);
  • Quando a execução é suspensa, observe o valor da variável this.sql;

Isso é para o hibernate 3. Não tenho certeza de que isso funcione em outras versões.


3

O driver mysql jdbc já fornece um conveniente para atender a esse requisito, você deve pelo menos ter a versão jar> = mysql-connect-jar-5.1.6.jar

etapa 1: [configure seu jdbc.url para adicionar logger e log personalizado]

    jdbc.url=jdbc:mysql://host:port/your_db?logger=com.mysql.jdbc.log.Slf4JLogger&profileSQL=true&profilerEventHandler=com.xxx.CustomLoggingProfilerEventHandler

agora, ele está usando o log slf4j, se o log padrão for log4j, você deve adicionar as dependências slf4j-api, slf4j-log4j12 para usar o log slf4j

etapa 2: [escreva seu log personalizado]

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

}

2

Eu gosto disso para 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 

Ei, isso é legal. Mas acho que aqui as consultas são impressas com o? seguido com os valores dos parâmetros. Como tenho inúmeras consultas, preciso de algo que possa copiar e colar no editor sql e elas serão executadas. Existe uma maneira de fazer isso usando essa abordagem. Não gosto muito de ir para bibliotecas de terceiros. Obrigado :)
dev ray

Obrigado. Eu esperava não precisar usar nenhuma solução de terceiros e hibernar diretamente, mas acho que não tenho outra opção.
ray dev

2

O registro funciona, mas não exatamente o que você quer ou eu queria há algum tempo, mas o P6Spy funciona perfeitamente ,

aqui está o tutorial simples de implementar também o tutorial MKYONG para P6Spy .

para mim, funcionou como charme.

  1. Download da biblioteca P6Spy

Obtenha o "p6spy-install.jar"

  1. Extraia-o

Extraia o p6spy-install.jararquivo, procure p6spy.jarespy.properties

  1. Adicionar dependência de biblioteca

Adicione p6spy.jarà sua dependência da biblioteca de projetos

  1. Modificar arquivo de propriedades do P6Spy

Modifique seu arquivo de configuração do banco de dados. Você precisa substituir o driver JDBC existente pelo driver P6Spy JDBC -com.p6spy.engine.spy.P6SpyDriver

Original é o driver 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>
  <property name="hibernate.connection.password">password</property>
  <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/mkyong</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>

Alterado para o driver 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>
  <property name="hibernate.connection.password">password</property>
  <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/mkyong</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. Modifique o arquivo de propriedades do P6Spy Modifique o arquivo de propriedades do P6Spy -spy.properties

Substitua real driverpor seu driver MySQL JDBC existente

realdriver=com.mysql.jdbc.Driver

#specifies another driver to use
realdriver2=
#specifies a third driver to use
realdriver3=

Alterar o local do arquivo de log Altere o local do arquivo de log na propriedade filefile, todas as instruções SQL farão logon neste arquivo.

janelas

logfile     = c:/spy.log

* nix

logfile     = /srv/log/spy.log
  1. Copiar “spy.properties”para o caminho de classe do projeto

Copie “spy.properties”para a pasta raiz do projeto, verifique se o seu projeto pode localizar "spy.properties"; caso contrário, ele solicitará a “spy.properties”exceção do arquivo não encontrado.


Esse foi o caminho mais fácil a seguir no meu aplicativo Spring Boot, onde estava tentando registrar o SQL gerado a partir de um teste de unidade. Adicionei uma dependência de teste ao Gradle (testCompile 'p6spy: p6spy: 3.8.5'), application.yml ajustado para definir spring.datasource.url = jdbc: p6spy: h2: mem: testdb e spring.datasource.driver-class- name = com.p6spy.engine.spy.P6SpyDriver e, em seguida, adicionou spy.properties com realdriver = org.h2.Driver e arquivo de log definido no meu caminho preferido. Foi fácil extrair o SQL completo do arquivo de log resultante. O único problema foi que o H2 não gostou do formato de carimbo de data e hora gerado.
Ken Pronovici 08/09/19

2

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


Como isso se relaciona com a pergunta?
hotzst

2

Usando o Hibernate 4 e slf4j / log4j2, tentei adicionar o seguinte na minha configuração 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>

Mas sem sucesso.

Eu descobri através deste thread que a estrutura do jboss-logging usada pelo hibernate precisava ser configurada para fazer o log do slf4j. Adicionei o seguinte argumento aos argumentos da VM do aplicativo:

-Dorg.jboss.logging.provider=slf4j

E funcionou perfeitamente.


2

Aqui está o que funcionou para mim, defina a propriedade abaixo no log4j.file:

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

Configurações de propriedades do Hibernate:

hibernate.show_sql=true

2

para desenvolvimento com o Wildfly (standalone.xml), adicione os registradores:

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

1

se você estiver usando o hibernate 3.2.xx, use

log4j.logger.org.hibernate.SQL=trace

ao invés de

log4j.logger.org.hibernate.SQL=debug 

1

Você pode registrar isso:

net.sf.hibernate.hql.QueryTranslator

Exemplo de saída:

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 )

Ei ... Não consigo encontrar exemplos dessa abordagem. Você poderia fornecer qualquer referência / exemplos / tutoriais. E ainda é o mesmo com as versões mais recentes ou hibernate / log4j ou se tornou algum org.hibernate.QueryTranslator ou algo assim. Graças
dev ray

Ei ... Eu tentei isso, mas isso não parece funcionar com salvar ou atualizar. Eu acho que ele só funciona para consultas SELECT, onde a tradução de hql para sql entra em jogo
ray dev

1

O plugin Log4Jdbc seria o melhor para sua necessidade. Mostra as seguintes

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

Consulte o link abaixo para configurar o Log4Jdbc-

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

1

Use Wireshark ou algo semelhante:

Nenhuma das respostas acima mencionadas imprimirá sql com parâmetros corretamente ou é uma dor. Consegui isso usando o WireShark , que captura todos os comandos sql / enviados do aplicativo para o Oracle / Mysql etc com as consultas.


2
Log4JDBC será. Veja acima.
Alan Hay

1

Todas as respostas aqui são úteis, mas se você estiver usando um XML de contexto de aplicativo Spring para configurar sua fábrica de sessões, a configuração da variável de nível SQL log4j fará com que você faça parte do caminho até lá, também precisará definir a variável hibernate.show_sql no próprio contexto do aplicativo, para que o Hibernate comece a realmente mostrar os valores.

O ApplicationContext.xml possui:

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

E seu arquivo log4j precisa

log4j.logger.org.hibernate.SQL=DEBUG

1

Em Java:

Transforme sua consulta em TypedQuery se for um CriteriaQuery (javax.persistence).

Então:

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


11
Obrigado, ele imprime a consulta, mas não os parâmetros que ele usou, existe uma maneira de imprimir os parâmetros também?
Liz Lamperouge

0

O Hibernate mostra a consulta e seus valores de parâmetro em linhas diferentes.

Se você estiver usando application.properties na inicialização por primavera e poderá usar o parâmetro destacado abaixo em application.properties.

  1. org.hibernate.SQL mostrará consultas

    logging.level.org.hibernate.SQL = DEBUG

  2. org.hibernate.type mostrará todos os valores de parâmetros, que serão mapeados com as consultas de seleção, inserção e atualização. logging.level.org.hibernate.type = TRACE

    • org.hibernate.type.EnumType mostrará o valor do parâmetro do tipo enum

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

      exemplo ::

      2018-06-14 11:06:28,217 TRACE [main] [EnumType.java : 321] Binding [active] to parameter: [1]
    • sql.BasicBinder mostrará o valor inteiro do parâmetro, varchar, tipo booleano

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

      exemplo ::

      • 2018-06-14 11: 28: 29.750 TRACE [http-nio-9891-exec-2] [BasicBinder.java: 65] parâmetro de ligação [1] como [BOOLEAN] - [true]
      • 2018-06-14 11: 28: 29.751 TRACE [http-nio-9891-exec-2] [BasicBinder.java: 65] parâmetro de ligação [2] como [INTEGER] - [1]
      • 2018-06-14 11: 28: 29.752 TRACE [http-nio-9891-exec-2] [BasicBinder.java: 65] parâmetro de ligação [3] como [VARCHAR] - [public]

11
Mesmo isso não mostra os valores para limite e deslocamento nas consultas.
precisa saber é

0

A solução mais simples para mim é implementar um stringReplace regular para substituir entradas de parâmetro por valores de parâmetro (tratar todos os parâmetros como string, para simplificar):

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

ou algo semelhante para parâmetros posicionais (?).
Cuide de valores nulos e tipos de valores específicos, como data, se desejar que um sql pronto para execução seja registrado.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.