Come visualizzare le query SQL emesse da JPA?


155

Quando il mio codice emette una chiamata come questa:

entityManager.find(Customer.class, customerID);

Come posso vedere la query SQL per questa chiamata? Supponendo che non ho accesso al server di database per profilare / monitorare le chiamate, esiste un modo per registrare o visualizzare nel mio IDE le corrispondenti query SQL emesse dalle chiamate JPA? Sto andando contro SQL Server 2008 R2 utilizzando il driver jTDS.


8
Cos'è il provider JPA? Credo che questa impostazione sia specifica del provider.
btiernay,

@Sajee, per favore, potresti contrassegnare la risposta di axtavt come accettata in modo che indirizzi i visitatori alla tua domanda direttamente a questa risposta?
8bitjunkie,

Risposte:


332

Le opzioni di registrazione sono specifiche del provider. Devi sapere quale implementazione JPA usi.

  • Ibernazione ( vedi qui ):

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

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

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

    Impostare la categoria di registro DataNucleus.Datastore.Nativesu un livello, ad esempio DEBUG.


4
@Sajee: dovresti dare a questa risposta un segno di spunta per indicare che questa è la risposta accettata. Funziona benissimo per me, usando Hibernate. Se approvi questa risposta, tu e il risponditore otterrete più punti e più autorizzazioni su stackoverflow.com.
LS

57
Inseriresti questa linea nel tuo persistence.xml per qualsiasi corpo che è curry. Sarebbe sotto il nodo <properties> ... Scusate se è ovvio, ero solo confuso su dove metterlo da solo.
SoftwareSavant,

5
Quando si utilizza Hibernate e log4j, è inoltre possibile impostare il logger "org.hibernate.SQL" su DEBUG ( javalobby.org/java/forums/t44119.html )
MosheElisha,

Inoltre, sembra che il nodo <properties> debba trovarsi al di sotto di tutto il resto all'interno di <persistence-unit>. <3 XML.
Tom Spurling,

1
Dove dovrebbero essere impostate queste proprietà?
Alex Worden,

34

Inoltre, se si utilizza EclipseLink e si desidera generare i valori dei parametri SQL, è possibile aggiungere questa proprietà al file persistence.xml:

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

Esiste un'alternativa per ottenere i valori di associazione in intellij?
Vinícius M,

15

Se si utilizza l'ibernazione e il logback come logger, è possibile utilizzare quanto segue (mostra solo i binding e non i risultati):

<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 stampa la query

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

org.hibernate.type = TRACE stampa i bind e normalmente i risultati, che saranno soppressi attraverso il filtro personalizzato

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

È necessaria la dipendenza 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

In EclipseLink per ottenere l'SQL per una query specifica in fase di runtime è possibile utilizzare 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();

Questo SQL conterrà? per i parametri. Per far tradurre l'SQL con gli argomenti è necessario un DatabaseRecord con i valori dei parametri.

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

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

Fonte: come ottenere l'SQL per una query


Che cos'è recordWithValues? È possibile ottenerlo da DatabaseQuery o EJBQueryImpl?
zmeda,

1
L'argomento Record è uno dei (Record, XMLRecord) che contiene gli argomenti della query
Tomasz,

Se ho qualcosa come Query myQuery = entityManager.createNamedQuery ("MyEntity.findMe"); myQuery.setParameter ("param1", "someValue); Come ottenere recordWithValues ​​da myQuery?
zmeda,

Aggiornato la mia risposta per includere la creazione di recordWithValues.
Tomasz,

Ehi, sai come fare per la schifezza di eclipseLink che non funziona con JPA? (Non so nemmeno cosa sia esattamente ma ha generato classi di mappatura da un'applicazione workbench .... Tuttavia non ho un EM ma solo un servizio toplink posso richiedere una sessione ma che non conosce alcuna query. utilizzare classi come ReadAllQuery, ExpressionBuilder ed Expression. Non è necessario rispondere se è troppo poco chiaro (non sono un professionista in questo, sono abituato a JPA) Eliminerò questo commento entro le prossime 48 ore e cercherò di porre una domanda più chiara;)
JBA,

7

Per visualizzare tutti i parametri SQL e in OpenJPA, inserire questi due parametri in persistence.xml:

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

5

Se si desidera visualizzare le query esatte insieme ai valori dei parametri e ai valori restituiti, è possibile utilizzare un driver proxy jdbc. Intercetterà tutte le chiamate jdbc e registrerà i loro valori. Alcuni proxy:

  • log4jdbc
  • jdbcspy

Possono anche fornire alcune funzionalità aggiuntive, come la misurazione dei tempi di esecuzione delle query e la raccolta di statistiche.


4

Esempio usando 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
Spiega un po 'di più la tua risposta. Presumo che la sezione principale sia la sezione org.hibernate.SQL?
JackDev,

2

Ho creato un cheat-sheet che penso possa essere utile agli altri. In tutti gli esempi, è possibile rimuovere la format_sqlproprietà se si desidera mantenere le query registrate su una sola riga (nessuna stampa carina).

Abbastanza stampa query SQL per standard senza parametri di istruzioni preparate e senza ottimizzazioni di un framework di registrazione :

application.properties file:

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

application.yml file:

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

Abbastanza stampa query SQL con parametri di istruzioni preparate utilizzando un framework di registrazione :

application.properties file:

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

application.yml file:

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

Stampa di query SQL senza parametri di istruzioni preparate utilizzando un framework di registrazione :

application.properties file:

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

application.yml file:

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

Fonte (e maggiori dettagli): https://www.baeldung.com/sql-logging-spring-boot


1

Inoltre, se si utilizza WildFly / JBoss, impostare il livello di registrazione di org.hibernate su DEBUG

Ibernazione Registrazione in WildFly


1

Un'altra buona opzione se hai troppi log e vuoi metterli solo come temporali System.out.println(), puoi, a seconda del tuo provider fare:

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());

Nella nostra implementazione basata su openjpa, questo non mostra i parametri come parte della query per una query parametrizzata.
Timwaagh,

1

Se si utilizza il framework Spring. Modifica il tuo file application.properties come di seguito

#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

Con Spring Boot è sufficiente aggiungere: spring.jpa.show-sql = true a application.properties. Questo mostrerà la query ma senza i parametri effettivi (vedrai? Invece di ogni parametro).


0

Durante lo sviluppo esplorativo e per focalizzare la registrazione del debug SQL sul metodo specifico che voglio controllare, decoro quel metodo con le seguenti istruzioni del logger:

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 per l'output di SQL (persistence.xml config):

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

-2

C'è un file chiamato persistence.xml Premi Ctrl + Maiusc + R e trovalo, poi c'è un posto scritto qualcosa come showSQL.

Mettilo come vero

Non sono sicuro se il server deve essere avviato come modalità di debug. Controlla gli SQL creati sulla console.


questo non è sufficiente per mostrare i parametri solo l'istruzione sql? per i parametri.
Ebuzer Taha KANAT,

1
"Qualcosa come showSQL" non è una risposta. e Ctrl + Maiusc + R? Hai formulato un'ipotesi sull'IDE.
8bitjunkie,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.