Comment imprimer une chaîne de requête avec des valeurs de paramètre lors de l'utilisation d'Hibernate


Réponses:


429

Vous devez activer la journalisation pour les catégories suivantes:

  • org.hibernate.SQL   - défini pour debugenregistrer toutes les instructions SQL DML lors de leur exécution
  • org.hibernate.type- réglé pour traceenregistrer tous les paramètres JDBC

Une configuration log4j pourrait donc ressembler à:

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

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

La première est équivalente à la propriétéhibernate.show_sql=true héritée , la seconde imprime entre autres les paramètres liés.

Une autre solution (non basée sur l'hibernation) serait d'utiliser un pilote proxy JDBC comme P6Spy .


11
C'est utile. Mais cela ne me montre pas les vraies requêtes SQL.
Nicolas Barbulesco

6
@Nicolas, c'est vrai, mais immédiatement après la requête, il affiche les paramètres liés.
Xtreme Biker

2
J'utilise Grails 2.4.4 et hibernate 4. Changer la configuration de log4j n'a pas fonctionné pour moi mais p6spy a fonctionné!
Champ

11
Dans Hibernate 5, nous pouvons utiliser l' org.hibernate.type.descriptor.sql.BasicBinderenregistreur. Activer la connexion sur org.hibernate.typeimprimé trop d'informations inutiles pour moi ...
csharpfolk

5
org.hibernate.typeet org.hibernate.loader.hqlne fonctionne pas pour moi pour afficher les paramètres
Dherik

75

Pour plus de commodité, voici le même exemple de configuration pour 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>

La sortie dans votre sql.log (exemple) ressemble alors à ceci:

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
Cela ne répond pas à la question des PO.
ShadowGames

33

Changer hibernate.cfg.xmlpour:

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

Incluez log4j et les entrées ci-dessous dans "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

Merci, ça a très bien fonctionné pour moi. Ces paramètres ajouteront sous la requête SQL un paramètre comme binding parameter [1] as [VARCHAR] - [1].
G. Ciardini

29

En cas d'utilisation d'une botte de printemps, configurez simplement ceci:

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

Et rien de plus.

HTH


21

Log4JDBC est une bonne solution qui imprime le SQL exact allant à la base de données avec des paramètres en place plutôt que la réponse la plus populaire ici qui ne le fait pas. Un avantage majeur de ceci est que vous pouvez copier le SQL directement sur votre frontal DB et l'exécuter tel quel.

http://log4jdbc.sourceforge.net/

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

Ce dernier produit également une représentation tabulaire des résultats de la requête.

Exemple de sortie montrant le SQL généré avec des paramètres en place avec le tableau de l'ensemble de résultats de la requête:

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

Mise à jour 2016

Plus récemment, j'utilise maintenant log4jdbc-log4j2 ( https://code.google.com/archive/p/log4jdbc-log4j2/ ) avec SLF4j et logback. Les dépendances Maven requises pour ma configuration sont les suivantes:

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

Les URL du pilote et de la base de données ressemblent alors à:

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 

Mon fichier de configuration logback.xml ressemble à ce qui suit: cela génère toutes les instructions SQL avec des paramètres ainsi que les tables d'ensemble de résultats pour toutes les requêtes.

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

Enfin, j'ai dû créer un fichier nommé log4jdbc.log4j2.properties à la racine du chemin de classe, par exemple src / test / resources ou src / main / resources dans un projet Mevn. Ce fichier a une ligne qui est la suivante:

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

Ce qui précède dépendra de votre bibliothèque de journalisation. Consultez la documentation sur https://code.google.com/archive/p/log4jdbc-log4j2 pour plus d'informations.

Exemple de sortie:

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

1
Hé .... Cela semble cool .... juste ce que le médecin a commandé pour moi :) ... mais cela prend-il également en charge CLOB / BLOB ?? Il est également possible d'afficher uniquement la requête et non l'ensemble de résultats. - Merci :)
dev ray

1
pourriez-vous me donner un exemple de configuration comment faire?
grep

En fait, ce dernier produit une représentation tabulaire des résultats de la requête ... c'est-à-dire qu'il faut log4jdbc-remix pour cette fonctionnalité intéressante.
meriton

Cette solution était la mieux adaptée à ma situation où j'avais besoin de voir les valeurs des numéros de ligne générées par Hibernate pour les jeux de résultats de pagination. La journalisation de trace affiche uniquement les valeurs des paramètres de requête.
Oliver Hernandez

@Alan Hay enregistre-t-il également les requêtes natives?
Sayantan

9

Vous pouvez ajouter des lignes de catégorie à log4j.xml:

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

et ajouter des propriétés d'hibernation:

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

7

ajoutez les propriétés et valeurs suivantes à votre configuration log4j ou logback:

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

5
La org.hibernate.type.descriptor.sql.BasicBindercatégorie n'inclut pas tous les paramètres, par exemple les types d'énumération. Donc, si vous voulez tout, vous avez vraiment besoin TRACEde tout le org.hibernate.typegroupe.
seanf

Pour moi, cela fonctionne dans Hibernate 4.3! De plus, je ne suivrais pas le org.hibernate.type complet, car c'est beaucoup trop de sortie. Dans la plupart des cas, cette solution fera l'affaire.
cslotty

Notez que org.hibernate.type.descriptor.sql.BasicExtractor enregistre les jeux de résultats. Donc, avoir une entrée de grande taille peut même planter l'application lors de la connexion à la console dans Eclipse, et je suppose que ce n'est pas non plus idéal pour se connecter au fichier. C'est pourquoi je préfère cette solution, elle fonctionne également dans Hibernate 3. Pour ceux qui sont intéressés par les types d'énumération, veuillez essayer la classe exacte qui les enregistre lorsque org.hibernate.type = TRACE. Ensuite, définissez org.hibernate.type.xyz.TheClassThatLogsEnumParams = TRACE.
Géza

7

Vous pouvez le faire en utilisant le proxy de source de données , comme je l'ai décrit dans cet article .

En supposant que votre application attend un dataSourcebean (par exemple via @Resource), voici comment configurer 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"/>

Maintenant, la sortie 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]}

Les datasource-proxyrequêtes contiennent des valeurs de paramètres et vous pouvez même ajouter des intercepteurs d'instructions JDBC personnalisés afin de pouvoir détecter les problèmes de requête N + 1 directement à partir de vos tests d'intégration .


5

allumez l' org.hibernate.typeenregistreur pour voir comment les paramètres réels sont liés aux points d'interrogation.


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

La solution est correcte mais enregistre également toutes les liaisons pour les objets de résultat. Pour éviter cela, il est possible de créer un appender séparé et d'activer le filtrage, par exemple:

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

Les lignes simples au-dessus de 31 doivent être ajoutées dans votre fichier de configuration d'hibernation, cela fonctionnera certainement. Je poste toujours des choses que j'ai faites pratiquement.
Vijay Bhatt

3

Cette réponse est un peu différente pour la question. Parfois, nous n'avons besoin de sql qu'à des fins de débogage lors de l'exécution. Dans ce cas, il existe un moyen plus simple d'utiliser le débogage sur les éditeurs.

  • Mettez un point d'arrêt sur org.hibernate.loader.Loader.loadEntityBatch (ou naviguez sur la pile jusque là);
  • Lorsque l'exécution est suspendue, regardez la valeur de la variable this.sql;

C'est pour la mise en veille prolongée 3. Je ne suis pas sûr que cela fonctionne sur d'autres versions.


3

Le pilote mysql jdbc a déjà fourni un moyen pratique pour répondre à cette exigence, vous devez au moins avoir la version jar> = mysql-connect-jar-5.1.6.jar

étape 1: [configurez votre jdbc.url pour ajouter un enregistreur et une journalisation personnalisée]

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

maintenant, il utilise la journalisation slf4j, si votre journalisation par défaut est log4j, vous devez ajouter les dépendances slf4j-api, slf4j-log4j12 pour utiliser la journalisation slf4j

étape 2: [rédigez votre journal personnalisé]

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

J'aime ça pour 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 

Hé - c'est sympa. Mais je pense qu'ici les requêtes sont imprimées avec le? suivi des valeurs des paramètres. Puisque j'ai infiniment de requêtes, j'ai besoin de quelque chose que je peux simplement copier-coller sur l'éditeur sql et elles seront exécutées. Existe-t-il un moyen de le faire en utilisant cette approche. Je ne suis pas si désireux d'aller pour des bibliothèques tierces. Merci :)
dev ray

Merci. J'espérais ne pas avoir à utiliser de solutions tierces et hiberner directement, mais je suppose que je n'ai pas d'autre choix.
dev ray

2

La journalisation fonctionne mais pas exactement ce que vous voulez ou je voulais il y a quelque temps, mais P6Spy fonctionne parfaitement ,

voici le tutoriel simple à mettre en œuvre ainsi que le tutoriel MKYONG pour P6Spy .

pour moi, cela a fonctionné comme un charme.

  1. Télécharger la bibliothèque P6Spy

Obtenez le «p6spy-install.jar»

  1. Extraire

Extrayez le p6spy-install.jarfichier, recherchez p6spy.jaretspy.properties

  1. Ajouter une dépendance de bibliothèque

Ajoutez p6spy.jarà votre dépendance de bibliothèque de projet

  1. Modifier le fichier de propriétés P6Spy

Modifiez votre fichier de configuration de base de données. Vous devez remplacer votre pilote JDBC existant par un pilote JDBC P6Spy -com.p6spy.engine.spy.P6SpyDriver

L'original est le pilote 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>

Changé en pilote JDBC P6Spy - 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. Modifier le fichier de propriétés P6Spy Modifier le fichier de propriétés P6Spy -spy.properties

Remplacez le real driverpar votre pilote JDBC MySQL existant

realdriver=com.mysql.jdbc.Driver

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

Modifier l'emplacement du fichier journal Modifiez l'emplacement du fichier journal dans la propriété logfile, toutes les instructions SQL se connecteront à ce fichier.

les fenêtres

logfile     = c:/spy.log

*rien

logfile     = /srv/log/spy.log
  1. Copier “spy.properties”dans le chemin de classe du projet

Copiez “spy.properties”dans le dossier racine de votre projet, assurez-vous que votre projet peut localiser «spy.properties», sinon il invitera une “spy.properties”exception de fichier introuvable.


C'était la voie la plus simple pour moi dans mon application Spring Boot, où j'essayais de consigner le SQL généré à partir d'un test unitaire. J'ai ajouté une dépendance de test à Gradle (testCompile 'p6spy: p6spy: 3.8.5'), ajusté application.yml pour définir spring.datasource.url = jdbc: p6spy: h2: mem: testdb et spring.datasource.driver-class- name = com.p6spy.engine.spy.P6SpyDriver, puis ajouté spy.properties avec realdriver = org.h2.Driver et fichier journal définis sur mon chemin préféré. Il était facile d'extraire le SQL complet du fichier journal résultant. Le seul hic était que H2 n'aimait pas le format d'horodatage généré.
Ken Pronovici

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>


Quel est le rapport avec la question?
hotzst

2

En utilisant Hibernate 4 et slf4j / log4j2, j'ai essayé d'ajouter les éléments suivants dans ma configuration 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>

Mais sans succès.

J'ai découvert à travers ce fil que le framework jboss-logging utilisé par hibernate devait être configuré afin de se connecter via slf4j. J'ai ajouté l'argument suivant aux arguments VM de l'application:

-Dorg.jboss.logging.provider=slf4j

Et ça a fonctionné comme un charme.


2

Voici ce qui a fonctionné pour moi, défini ci-dessous dans le fichier log4j.file:

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

Paramètres des propriétés de mise en veille prolongée:

hibernate.show_sql=true

2

pour le développement avec Wildfly (standalone.xml), ajoutez ces enregistreurs:

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

1

si vous utilisez hibernate 3.2.xx, utilisez

log4j.logger.org.hibernate.SQL=trace

au lieu de

log4j.logger.org.hibernate.SQL=debug 

1

Vous pouvez vous connecter:

net.sf.hibernate.hql.QueryTranslator

Exemple de sortie:

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 )

Hé ... je ne trouve aucun exemple de cette approche. Pourriez-vous fournir des références / exemples / tutoriels. Et est-ce toujours la même chose avec les dernières versions ou hibernate / log4j ou est-il devenu un org.hibernate.QueryTranslator ou quelque chose. Merci
dev ray

Hé ... J'ai essayé cela, mais cela ne semble pas fonctionner avec la sauvegarde ou la mise à jour. Je suppose que cela ne fonctionne que pour certaines requêtes, où la traduction de hql en sql entre en jeu
dev ray

1

Le plugin Log4Jdbc serait le mieux adapté à vos besoins. Cela montre:

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

Référez-vous au lien ci-dessous pour configurer Log4Jdbc-

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

1

Utilisez Wireshark ou quelque chose de similaire:

Aucune des réponses mentionnées ci-dessus n'imprimera correctement sql avec des paramètres ou n'est une douleur. J'ai atteint cet objectif en utilisant WireShark , qui capture toutes les commandes sql / envoyées de l'application à Oracle / Mysql, etc. avec les requêtes.


2
Log4JDBC le fera. Voir au dessus.
Alan Hay

1

Toutes les réponses ici sont utiles, mais si vous utilisez un XML de contexte d'application Spring pour configurer votre fabrique de sessions, la définition de la variable de niveau log4j SQL ne vous y permet que partiellement, vous devez également définir la variable hibernate.show_sql dans le contexte de l'application elle-même pour que Hibernate commence à afficher réellement les valeurs.

ApplicationContext.xml a:

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

Et votre fichier log4j a besoin

log4j.logger.org.hibernate.SQL=DEBUG

1

En Java:

Transformez votre requête en TypedQuery s'il s'agit d'une requête de critères (javax.persistence).

Alors:

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


1
Merci, il imprime la requête, mais pas les paramètres qu'il a utilisés, il y a aussi un moyen d'imprimer les paramètres?
Liz Lamperouge

0

Hibernate affiche la requête et leurs valeurs de paramètre sur différentes lignes.

Si vous utilisez application.properties dans Spring Boot et que vous pouvez utiliser le paramètre en surbrillance ci-dessous dans application.properties.

  1. org.hibernate.SQL affichera les requêtes

    logging.level.org.hibernate.SQL = DEBUG

  2. org.hibernate.type affichera toutes les valeurs des paramètres, qui seront mappées avec les requêtes de sélection, d'insertion et de mise à jour. logging.level.org.hibernate.type = TRACE

    • org.hibernate.type.EnumType affichera la valeur du paramètre de type enum

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

      exemple ::

      2018-06-14 11:06:28,217 TRACE [main] [EnumType.java : 321] Binding [active] to parameter: [1]
    • sql.BasicBinder affichera la valeur du paramètre de type entier, varchar, booléen

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

      exemple ::

      • 2018-06-14 11: 28: 29,750 TRACE [http-nio-9891-exec-2] [BasicBinder.java: 65] paramètre de liaison [1] en tant que [BOOLEAN] - [true]
      • 2018-06-14 11: 28: 29,751 TRACE [http-nio-9891-exec-2] [BasicBinder.java: 65] paramètre de liaison [2] comme [INTEGER] - [1]
      • 2018-06-14 11: 28: 29,752 TRACE [http-nio-9891-exec-2] [BasicBinder.java: 65] paramètre de liaison [3] en tant que [VARCHAR] - [public]

1
Même cela n'affiche pas les valeurs de limite et de décalage dans les requêtes.
T3rm1

0

La solution la plus simple pour moi consiste à implémenter un stringReplace normal pour remplacer les entrées de paramètres par des valeurs de paramètres (en traitant tous les paramètres comme des chaînes, pour plus de simplicité):

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

ou quelque chose de similaire pour les paramètres de position (?).
Prenez soin des valeurs nulles et des types de valeurs spécifiques comme la date, si vous voulez qu'un SQL prêt à être exécuté soit enregistré.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.