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.

Sajee
la source
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.

axtavt
la source
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"/>
ThePizzle
la source
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>
Kuhpid
la source
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

Tomasz
la source
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" />
jfcorugedo
la source
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.

mateusz.fiolka
la source
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>

Marcus Becker
la source
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

Kent Munthe Caspersen
la source
1

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

Journalisation Hibernate dans WildFly

Αλέκος
la source
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());
Le roi Midas
la source
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  
thyzz
la source
0

Voir Impossible de faire en sorte que la mise en veille prolongée cesse d'afficher SQL à l'aide de l'adaptateur de fournisseur Spring JPA

Btiernay
la source
Je n'utilise pas Hibernate. AFAIK, juste un vieux JPA. showSQL ressemble à une propriété Hibernate. Cela fonctionnera-t-il dans mon cas?
Sajee
On dirait que la réponse est non. Je ne vois aucun SQL dans les journaux.
Sajee
1
Sajee, comment déclarez-vous les propriétés de votre persistence.xml?
Gondim
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).

Elhanan Mishraky
la source
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);
Abdull
la source
0

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

<property name="eclipselink.logging.level.sql" value="FINE" />
ChameauTM
la source
-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.

Gondim
la source
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