2010-12-06 3 views
117

Lorsque mon code émet un appel comme celui-ci:Comment afficher les requêtes SQL émises par JPA?

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, y a-t-il moyen de consigner ou d'afficher dans mon EDI 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 crois que ce paramètre est spécifique au fournisseur. – btiernay

+0

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

Répondre

1

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

il suffit de mettre aussi 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.

+0

cela ne suffit pas pour montrer les paramètres SQL déclaration seulement montre? pour les paramètres. –

+0

"Quelque chose comme showSQL" n'est pas une réponse. et Ctrl + Maj + R? Vous avez fait une supposition à propos de l'IDE. – 8bitjunkie

279

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

  • Hibernate (see here):

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

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

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

    Définir la catégorie de journal DataNucleus.Datastore.Native à un niveau, comme DEBUG.

+4

@Sajee: Vous devez cocher cette case 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. –

+38

Vous mettriez cette ligne dans votre persistence.xml pour tout corps qui est currious. Ce serait sous le noeud ... Désolé si c'est évident, j'étais juste confus au sujet de l'endroit où le mettre moi-même. – SoftwareSavant

+5

Lorsque vous utilisez Hibernate et log4j, vous pouvez également définir "org.hibernate.SQL "logger à DEBUG (http://www.javalobby.org/java/forums/t44119.html) – MosheElisha

32

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

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

En EclipseLink pour obtenir le SQL pour une requête spécifique à 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 obtenir le SQL traduit 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: How to get the SQL for a Query

+0

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

+0

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

+0

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

12

Si vous utilisez mise en veille prolongée et logback que votre enregistreur, vous pouvez utiliser les éléments suivants (ne montre que les fixations et pas 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 fixations et normalement les résultats, qui seront supprimés à travers le filtre personnalisé

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

Vous devez le janino dépendance (http://logback.qos.ch/manual/filters.html#JaninoEventEvaluator):

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

Si vous voulez voir les requêtes exactes une Avec les valeurs de paramètres et les valeurs de retour, vous pouvez utiliser un pilote proxy jdbc. Il intercepte tous les appels jdbc et enregistre leurs valeurs. Quelques procurations:

  • log4jdbc
  • jdbcspy

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

7

Pour voir tous les SQL et paramètres OpenJPA, mettre 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" /> 
3

Exemple d'utilisation 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

1

De plus, si vous utilisez wildfly/JBoss, définissez le niveau de consignation de org.hibernate DEBUG

Hibernate Logging in WildFly

0

Une autre good option si vous avez trop de journal et que vous voulez seulement mettre en System.out.println() temporelle, 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()); 
Questions connexes