Comment afficher les requêtes SQL émises par JPA?


155

Lorsque mon code émet un appel comme celui-ci:

entityManager.find(Customer.class, customerID);

Comment puis-je voir la requête SQL pour cet appel? En supposant que je n'ai pas accès au serveur de base de données pour profiler / surveiller les appels, existe-t-il un moyen de consigner ou d'afficher dans mon IDE les requêtes SQL correspondantes émises par les appels JPA? Je vais contre SQL Server 2008 R2 en utilisant le pilote jTDS.


8
Qu'est-ce que le fournisseur JPA? Je pense que ce paramètre est spécifique au fournisseur.
btiernay

@Sajee s'il vous plaît pourriez-vous marquer la réponse d'axtavt comme acceptée afin qu'elle dirige les visiteurs vers votre question directement vers cette réponse?
8bitjunkie

Réponses:


332

Les options de journalisation sont spécifiques au fournisseur. Vous devez savoir quelle implémentation JPA vous utilisez.

  • Hibernate ( voir ici ):

    <property name = "hibernate.show_sql" value = "true" />
  • EclipseLink ( voir ici ):

    <property name="eclipselink.logging.level" value="FINE"/>
  • OpenJPA ( voir ici ):

    <property name="openjpa.Log" value="DefaultLevel=WARN,Runtime=INFO,Tool=INFO,SQL=TRACE"/>
  • DataNucleus ( voir ici ):

    Définissez la catégorie de journal DataNucleus.Datastore.Nativesur un niveau, comme DEBUG.


4
@Sajee: Vous devez cocher cette réponse pour indiquer que c'est la réponse acceptée. Cela fonctionne très bien pour moi, en utilisant Hibernate. Si vous approuvez cette réponse, vous et le répondeur obtiendrez plus de points et plus d'autorisations sur stackoverflow.com.
LS

57
Vous mettriez cette ligne dans votre persistence.xml pour tout corps curieux. Ce serait sous le nœud <properties> ... Désolé si cela est évident, je ne savais pas trop où le mettre moi-même.
SoftwareSavant

5
Lorsque vous utilisez Hibernate et log4j, vous pouvez également définir l'enregistreur «org.hibernate.SQL» sur DEBUG ( javalobby.org/java/forums/t44119.html )
MosheElisha

De plus, il semble que le nœud <properties> doit être sous tout le reste de <persistence-unit>. <3 XML.
Tom Spurling

1
Où ces propriétés doivent-elles être définies?
Alex Worden

34

De plus, si vous utilisez EclipseLink et que vous souhaitez afficher les valeurs des paramètres SQL, vous pouvez ajouter cette propriété à votre fichier persistence.xml:

<property name="eclipselink.logging.parameters" value="true"/>

Existe-t-il une alternative pour obtenir les valeurs de liaison dans intellij?
Vinícius M

15

Si vous utilisez la mise en veille prolongée et la connexion comme enregistreur, vous pouvez utiliser ce qui suit (affiche uniquement les liaisons et non les résultats):

<appender
    name="STDOUT"
    class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
        <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} -
            %msg%n</pattern>
    </encoder>
    <filter class="ch.qos.logback.core.filter.EvaluatorFilter">
        <evaluator>
            <expression>return message.toLowerCase().contains("org.hibernate.type") &amp;&amp;
                logger.startsWith("returning");</expression>
        </evaluator>
        <OnMismatch>NEUTRAL</OnMismatch>
        <OnMatch>DENY</OnMatch>
    </filter>
</appender>

org.hibernate.SQL = DEBUG imprime la requête

<logger name="org.hibernate.SQL">
    <level value="DEBUG" />
</logger>

org.hibernate.type = TRACE imprime les liaisons et normalement les résultats, qui seront supprimés via le filtre personnalisé

<logger name="org.hibernate.type">
    <level value="TRACE" />
</logger>

Vous avez besoin de la dépendance janino (http://logback.qos.ch/manual/filters.html#JaninoEventEvaluator):

<dependency>
    <groupId>org.codehaus.janino</groupId>
    <artifactId>janino</artifactId>
    <version>2.6.1</version>
</dependency>

15

Dans EclipseLink pour obtenir le SQL pour une requête spécifique au moment de l'exécution, vous pouvez utiliser l'API DatabaseQuery:

Query query = em.createNamedQuery("findMe"); 
Session session = em.unwrap(JpaEntityManager.class).getActiveSession(); 
DatabaseQuery databaseQuery = ((EJBQueryImpl)query).getDatabaseQuery(); 
databaseQuery.prepareCall(session, new DatabaseRecord());

String sqlString = databaseQuery.getSQLString();

Ce SQL contiendra? pour les paramètres. Pour faire traduire le SQL avec les arguments, vous avez besoin d'un DatabaseRecord avec les valeurs des paramètres.

DatabaseRecord recordWithValues= new DatabaseRecord();
recordWithValues.add(new DatabaseField("param1"), "someValue");

String sqlStringWithArgs = 
         databaseQuery.getTranslatedSQLString(session, recordWithValues);

Source: Comment obtenir le SQL pour une requête


Qu'est-ce que recordWithValues? Est-il possible de l'obtenir à partir de DatabaseQuery ou EJBQueryImpl?
zmeda

1
L'argument Record est l'un des (Record, XMLRecord) qui contient les arguments de la requête
Tomasz

Si j'ai quelque chose comme Query myQuery = entityManager.createNamedQuery ("MyEntity.findMe"); myQuery.setParameter ("param1", "someValue); Comment obtenir recordWithValues ​​de myQuery?
zmeda

Mise à jour de ma réponse pour inclure la création recordWithValues.
Tomasz

Hé, savez-vous comment faire cela pour la merde eclipseLink qui ne fonctionne pas avec JPA? (Je ne sais même pas ce que c'est exactement mais il a généré des classes de mappage à partir d'une application de workbench .... Cependant, je n'ai pas d'EM mais seulement un service de liaison supérieure, je peux demander une session mais cela ne connaît aucune requête. Je utilisez des classes comme ReadAllQuery, ExpressionBuilder et Expression. Vous n'avez pas besoin de répondre si ce n'est pas clair (je ne suis pas un pro dans ce domaine, je suis habitué à JPA) je supprimerai ce commentaire dans les 48 prochaines heures et j'essaierai de poser une question plus claire;)
JBA

7

Afin de voir tous les SQL et paramètres dans OpenJPA, mettez ces deux paramètres dans le persistence.xml:

<property name="openjpa.Log" value="DefaultLevel=WARN, Runtime=INFO, Tool=INFO, SQL=TRACE"/>
<property name="openjpa.ConnectionFactoryProperties" value="PrintParameters=true" />

5

Si vous voulez voir les requêtes exactes avec les valeurs de paramètre et les valeurs de retour, vous pouvez utiliser un pilote de proxy jdbc. Il interceptera tous les appels jdbc et enregistrera leurs valeurs. Quelques procurations:

  • log4jdbc
  • jdbcspy

Ils peuvent également fournir des fonctionnalités supplémentaires, telles que la mesure du temps d'exécution des requêtes et la collecte de statistiques.


4

Exemple utilisant log4j ( src \ log4j.xml ):

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

<appender name="CA" class="org.apache.log4j.AsyncAppender">
    <param name="BufferSize" value="512"/>
    <appender-ref ref="CA_OUTPUT"/>
</appender>
<appender name="CA_OUTPUT" class="org.apache.log4j.ConsoleAppender">
    <layout class="org.apache.log4j.PatternLayout">
        <param name="ConversionPattern" value="[%p] %d %c %M - %m%n"/>
    </layout>
</appender>

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

<root>
    <level value="WARN"/>
    <appender-ref ref="CA"/>
</root>


1
Veuillez expliquer votre réponse un peu plus. Je suppose que la section principale est la section org.hibernate.SQL?
JackDev

2

J'ai fait une feuille de triche qui, je pense, peut être utile aux autres. Dans tous les exemples, vous pouvez supprimer la format_sqlpropriété si vous souhaitez conserver les requêtes enregistrées sur une seule ligne (pas de jolie impression).

Jolies requêtes SQL d'impression à standard sans paramètres d'instructions préparées et sans optimisations d'un framework de journalisation :

application.properties fichier:

spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true

application.yml fichier:

spring:
  jpa:
    show-sql: true
    properties:
      hibernate:
        format_sql: true

Jolies requêtes SQL d'impression avec des paramètres d'instructions préparées à l'aide d'un cadre de journalisation :

application.properties fichier:

spring.jpa.properties.hibernate.format_sql=true
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE

application.yml fichier:

spring:
  jpa:
    properties:
      hibernate:
        format_sql: true
logging:
  level:
    org:
      hibernate:
        SQL: DEBUG
        type:
          descriptor:
            sql:
              BasicBinder: TRACE

Jolies requêtes SQL d'impression sans paramètres d'instructions préparées à l'aide d'un cadre de journalisation :

application.properties fichier:

spring.jpa.properties.hibernate.format_sql=true
logging.level.org.hibernate.SQL=DEBUG

application.yml fichier:

spring:
  jpa:
    properties:
      hibernate:
        format_sql: true
logging:
  level:
    org:
      hibernate:
        SQL: DEBUG

Source (et plus de détails): https://www.baeldung.com/sql-logging-spring-boot


1

De plus, si vous utilisez WildFly / JBoss, définissez le niveau de journalisation de org.hibernate sur DEBUG

Journalisation Hibernate dans WildFly


1

Une autre bonne option si vous avez trop de journal et que vous ne voulez mettre que temporel System.out.println(), vous pouvez, en fonction de votre fournisseur faire:

CriteriaBuilder criteriaBuilder = getEntityManager().getCriteriaBuilder();
CriteriaQuery<ExaminationType> criteriaQuery = criteriaBuilder.createQuery(getEntityClass()); 

/* For Hibernate */
System.out.println(getEntityManager().createQuery(criteriaQuery).unwrap(org.hibernate.Query.class).getQueryString());

/* For OpenJPA */ 
System.out.println(getEntityManager().createQuery(criteriaQuery).unwrap(org.apache.openjpa.persistence.QueryImpl.class).getQueryString());

/* For EclipseLink */
System.out.println(getEntityManager().createQuery(criteriaQuery).unwrap(JpaQuery.class).getSQLString());

Dans notre implémentation basée sur openjpa, cela n'affiche pas les paramètres dans le cadre de la requête pour une requête paramétrée.
timwaagh

1

Si vous utilisez Spring Framework. Modifiez votre fichier application.properties comme ci-dessous

#Logging JPA Queries, 1st line Log Query. 2nd line Log parameters of prepared statements 
logging.level.org.hibernate.SQL=DEBUG  
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE  

#Logging JdbcTemplate Queries, 1st line Log Query. 2nd line Log parameters of prepared statements 
logging.level.org.springframework.jdbc.core.JdbcTemplate=DEBUG  
logging.level.org.springframework.jdbc.core.StatementCreatorUtils=TRACE  


0

Avec Spring Boot, ajoutez simplement: spring.jpa.show-sql = true à application.properties. Cela affichera la requête mais sans les paramètres réels (vous verrez? Au lieu de chaque paramètre).


0

Pendant le développement exploratoire et pour concentrer la journalisation du débogage SQL sur la méthode spécifique que je veux vérifier, je décore cette méthode avec les instructions de journalisation suivantes:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ch.qos.logback.classic.Level;

((ch.qos.logback.classic.Logger) LoggerFactory.getLogger("org.hibernate.SQL")).setLevel(Level.DEBUG);
entityManager.find(Customer.class, customerID);
((ch.qos.logback.classic.Logger) LoggerFactory.getLogger("org.hibernate.SQL")).setLevel(Level.INFO);

0

EclipseLink pour sortir le SQL (configuration persistence.xml):

<property name="eclipselink.logging.level.sql" value="FINE" />

-2

Il y a un fichier appelé persistence.xml Appuyez sur Ctrl + Maj + R et trouvez-le, puis, il y a un endroit écrit quelque chose comme showSQL.

Dis-le juste comme vrai

Je ne sais pas si le serveur doit être démarré en mode débogage. Vérifiez les SQL créés sur la console.


ce n'est pas suffisant pour afficher les paramètres instruction sql ne montre que? pour les paramètres.
Ebuzer Taha KANAT

1
"Quelque chose comme showSQL" n'est pas une réponse. et Ctrl + Maj + R? Vous avez fait une hypothèse sur l'EDI.
8bitjunkie
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.