Wie werden die von JPA ausgegebenen SQL-Abfragen angezeigt?

155

Wenn mein Code einen Aufruf wie diesen ausgibt:

entityManager.find(Customer.class, customerID);

Wie kann ich die SQL-Abfrage für diesen Aufruf sehen? Angenommen, ich habe keinen Zugriff auf den Datenbankserver, um die Anrufe zu profilieren / überwachen. Gibt es eine Möglichkeit, die entsprechenden SQL-Abfragen, die von JPA-Aufrufen ausgegeben werden, in meiner IDE zu protokollieren oder anzuzeigen? Ich gehe gegen SQL Server 2008 R2 mit dem jTDS-Treiber.

Sajee
quelle
8
Was ist der JPA-Anbieter? Ich glaube, diese Einstellung ist anbieterspezifisch.
btiernay
@Sajee, können Sie die Antwort von axtavt als akzeptiert markieren, damit die Besucher auf Ihre Frage direkt zu dieser Antwort weitergeleitet werden?
8bitjunkie

Antworten:

332

Die Protokollierungsoptionen sind anbieterspezifisch. Sie müssen wissen, welche JPA-Implementierung Sie verwenden.

  • Ruhezustand ( siehe hier ):

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

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

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

    Stellen Sie die Protokollkategorie DataNucleus.Datastore.Nativeauf eine Ebene wie ein DEBUG.

axtavt
quelle
4
@Sajee: Sie sollten dieser Antwort ein Häkchen geben, um anzuzeigen, dass dies die akzeptierte Antwort ist. Mit Hibernate funktioniert es hervorragend für mich. Wenn Sie dieser Antwort zustimmen, erhalten Sie und der Antwortende auf stackoverflow.com mehr Punkte und mehr Berechtigungen.
LS
57
Sie würden diese Zeile in Ihre persistence.xml für jeden Körper einfügen, der aktuell ist. Es würde sich unter dem Knoten <properties> befinden ... Entschuldigung, wenn das offensichtlich ist, war ich nur verwirrt darüber, wo ich es selbst ablegen soll.
SoftwareSavant
5
Wenn Sie Hibernate und log4j verwenden, können Sie den Logger "org.hibernate.SQL" auch auf DEBUG ( javalobby.org/java/forums/t44119.html ) setzen
MosheElisha
Darüber hinaus scheint sich der Knoten <properties> unter allem anderen innerhalb der <persistence-unit> zu befinden. <3 XML.
Tom Spurling
1
Wo sollen diese Eigenschaften eingestellt werden?
Alex Worden
34

Wenn Sie EclipseLink verwenden und die SQL-Parameterwerte ausgeben möchten, können Sie diese Eigenschaft Ihrer Datei persistence.xml hinzufügen:

<property name="eclipselink.logging.parameters" value="true"/>
ThePizzle
quelle
Gibt es eine Alternative, um die Bindungswerte in Intellij zu erhalten?
Vinícius M
15

Wenn Sie den Ruhezustand und den Logback als Logger verwenden, können Sie Folgendes verwenden (zeigt nur die Bindungen und nicht die Ergebnisse an):

<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 druckt die Abfrage

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

org.hibernate.type = TRACE druckt die Bindungen und normalerweise die Ergebnisse, die durch den benutzerdefinierten Filter unterdrückt werden

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

Sie benötigen die Janino-Abhängigkeit (http://logback.qos.ch/manual/filters.html#JaninoEventEvaluator):

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

In EclipseLink können Sie die DatabaseQuery-API verwenden, um die SQL für eine bestimmte Abfrage zur Laufzeit abzurufen:

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

Diese SQL wird enthalten? für Parameter. Um die SQL mit den Argumenten zu übersetzen, benötigen Sie einen DatabaseRecord mit den Parameterwerten.

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

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

Quelle: So erhalten Sie SQL für eine Abfrage

Tomasz
quelle
Was ist recordWithValues? Ist es möglich, es von DatabaseQuery oder EJBQueryImpl abzurufen?
Zmeda
1
Das Record-Argument ist eines von (Record, XMLRecord), das die Abfrageargumente enthält
Tomasz
Wenn ich so etwas wie Query myQuery = entityManager.createNamedQuery ("MyEntity.findMe") habe; myQuery.setParameter ("param1", "someValue); Wie bekomme ich recordWithValues ​​von myQuery?
zmeda
Meine Antwort wurde aktualisiert, um die Erstellung von recordWithValues ​​einzuschließen.
Tomasz
Hey, weißt du, wie man das für den eclipseLink-Mist macht, der nicht mit JPA läuft? (Ich weiß nicht einmal genau, was es ist, aber es hat Mapping-Klassen aus einer Workbench-Anwendung generiert. Allerdings habe ich keine EM, sondern nur einen Toplink-Service. Ich kann eine Sitzung anfordern, aber das kennt keine Abfrage Verwenden Sie Klassen wie ReadAllQuery, ExpressionBuilder und Expression. Sie müssen nicht antworten, wenn es zu unklar ist (ich bin kein Profi, ich bin an JPA gewöhnt). Ich werde diesen Kommentar innerhalb der nächsten 48 Stunden löschen und versuchen, eine klarere Frage zu stellen.
JBA
7

Fügen Sie diese beiden Parameter in die Datei persistence.xml ein, um alle SQL- und Parameter in OpenJPA anzuzeigen:

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

Wenn Sie die genauen Abfragen mit Parameterwerten und Rückgabewerten anzeigen möchten, können Sie einen JDBC-Proxy-Treiber verwenden. Es werden alle JDBC-Aufrufe abgefangen und ihre Werte protokolliert. Einige Proxies:

  • log4jdbc
  • jdbcspy

Sie bieten möglicherweise auch einige zusätzliche Funktionen, z. B. das Messen der Ausführungszeit für Abfragen und das Sammeln von Statistiken.

mateusz.fiolka
quelle
4

Beispiel mit 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
quelle
1
Bitte erläutern Sie Ihre Antwort etwas genauer. Ich nehme an, der Hauptabschnitt ist der org.hibernate.SQL-Abschnitt?
JackDev
1

Wenn Sie WildFly / JBoss verwenden, setzen Sie außerdem die Protokollierungsstufe von org.hibernate auf DEBUG

Ruhezustand Anmelden in WildFly

Αλέκος
quelle
1

Eine weitere gute Option, wenn Sie zu viel Protokoll haben und nur als temporäres Protokoll verwenden möchten System.out.println(), können Sie je nach Anbieter Folgendes tun:

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());
König Midas
quelle
In unserer openjpa-basierten Implementierung werden die Parameter nicht als Teil der Abfrage für eine parametrisierte Abfrage angezeigt.
Timwaagh
1

Wenn Sie das Spring Framework verwenden. Ändern Sie die Datei application.properties wie folgt

#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
quelle
1

Ich habe einen Spickzettel erstellt, von dem ich denke, dass er für andere nützlich sein kann. In allen Beispielen können Sie das entfernenformat_sql Eigenschaft wenn Sie die protokollierten Abfragen in einer einzelnen Zeile halten möchten (kein hübsches Drucken).

Hübsche SQL-Abfragen zum Standardisieren ohne Parameter vorbereiteter Anweisungen und ohne Optimierungen eines Protokollierungsframeworks :

application.properties Datei:

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

application.yml Datei:

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

Hübsche SQL-Abfragen mit Parametern vorbereiteter Anweisungen unter Verwendung eines Protokollierungsframeworks drucken :

application.properties Datei:

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

application.yml Datei:

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

Hübsche Druck-SQL-Abfragen ohne Parameter vorbereiteter Anweisungen unter Verwendung eines Protokollierungsframeworks :

application.properties Datei:

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

application.yml Datei:

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

Quelle (und weitere Details): https://www.baeldung.com/sql-logging-spring-boot

Kent Munthe Caspersen
quelle
0

Siehe Der Ruhezustand kann die Anzeige von SQL mit dem Spring JPA Vendor Adapter nicht beenden

Übrigens
quelle
Ich benutze Hibernate nicht. AFAIK, einfach nur alte JPA. showSQL sieht aus wie eine Hibernate-Eigenschaft. Wird das in meinem Fall funktionieren?
Sajee
Die Antwort lautet anscheinend Nein. Ich sehe kein SQL in den Protokollen.
Sajee
1
Sajee, wie deklarieren Sie die Eigenschaften in Ihrer persistence.xml?
Gondim
0

Fügen Sie mit Spring Boot einfach Folgendes hinzu: spring.jpa.show-sql = true to application.properties. Dies zeigt die Abfrage, jedoch ohne die tatsächlichen Parameter (Sie sehen? Anstelle jedes Parameters).

Elhanan Mishraky
quelle
0

Während der explorativen Entwicklung und um die SQL-Debugging-Protokollierung auf die spezifische Methode zu konzentrieren, die ich überprüfen möchte, dekoriere ich diese Methode mit den folgenden Logger-Anweisungen:

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

EclipseLink zur Ausgabe von SQL (persistence.xml config):

<property name="eclipselink.logging.level.sql" value="FINE" />
CamelTM
quelle
-2

Es gibt eine Datei namens persistence.xml. Drücken Sie Strg + Umschalt + R und finden Sie sie. Dann gibt es einen Ort, der so etwas wie showSQL geschrieben hat.

Sagen Sie es einfach als wahr

Ich bin nicht sicher, ob der Server als Debug-Modus gestartet werden muss. Überprüfen Sie die auf der Konsole erstellten SQLs.

Gondim
quelle
Dies ist nicht genug, um Parameter anzuzeigen. SQL-Anweisung zeigt nur? für Parameter.
Ebuzer Taha KANAT
1
"So etwas wie showSQL" ist keine Antwort. und Strg + Umschalt + R? Sie haben eine Annahme über die IDE gemacht.
8bitjunkie