Jak wyświetlić zapytania SQL wysłane przez JPA?


155

Kiedy mój kod wywołuje takie wywołanie:

entityManager.find(Customer.class, customerID);

Jak mogę zobaczyć zapytanie SQL dla tego wywołania? Zakładając, że nie mam dostępu do serwera bazy danych w celu profilowania / monitorowania połączeń, czy istnieje sposób na rejestrowanie lub przeglądanie w moim IDE odpowiednich zapytań SQL wysyłanych przez wywołania JPA? Idę na SQL Server 2008 R2 używając sterownika jTDS.


8
Co to jest dostawca JPA? Uważam, że to ustawienie jest specyficzne dla dostawcy.
btiernay

@Sajee, czy mógłbyś oznaczyć odpowiedź axtavt jako zaakceptowaną, aby kierowała odwiedzających do Twojego pytania bezpośrednio do tej odpowiedzi?
8bitjunkie

Odpowiedzi:


332

Opcje rejestrowania są zależne od dostawcy. Musisz wiedzieć, której implementacji JPA używasz.

  • Hibernacja ( patrz tutaj ):

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

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

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

    Ustaw kategorię dziennika DataNucleus.Datastore.Nativena poziom, na przykład DEBUG.


4
@Sajee: Powinieneś zaznaczyć tę odpowiedź znacznikiem wyboru, aby wskazać, że jest to zaakceptowana odpowiedź. U mnie działa świetnie, używając Hibernate. Jeśli zaakceptujesz tę odpowiedź, Ty i osoba odpowiadająca otrzymacie więcej punktów i więcej uprawnień na stackoverflow.com.
LS

57
Możesz umieścić ten wiersz w swoim persistence.xml dla każdego ciekawego ciała. Byłby pod węzłem <properties> ... Przepraszam, jeśli to oczywiste, po prostu nie wiedziałem, gdzie go umieścić.
SoftwareSavant

5
Korzystając z Hibernate i log4j, możesz również ustawić program rejestrujący „org.hibernate.SQL” na DEBUG ( javalobby.org/java/forums/t44119.html )
MosheElisha

Dodatkowo wydaje się, że węzeł <properties> musi znajdować się pod wszystkim innym w <persistence-unit>. <3 XML.
Tom Spurling

1
Gdzie należy ustawić te właściwości?
Alex Worden

34

Ponadto, jeśli używasz EclipseLink i chcesz wyprowadzić wartości parametrów SQL, możesz dodać tę właściwość do swojego pliku persistence.xml:

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

Czy istnieje alternatywa dla uzyskania wiążących wartości w intellij?
Vinícius M

15

Jeśli używasz hibernacji i logowania jako loggera, możesz użyć następujących elementów (pokazuje tylko powiązania, a nie wyniki):

<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 drukuje zapytanie

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

org.hibernate.type = TRACE wypisuje powiązania i normalnie wyniki, które zostaną pominięte przez niestandardowy filtr

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

Potrzebujesz zależności 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

W EclipseLink, aby uzyskać SQL dla konkretnego zapytania w czasie wykonywania, możesz użyć interfejsu 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();

Ten SQL będzie zawierał? dla parametrów. Aby uzyskać tłumaczenie SQL z argumentami, potrzebujesz DatabaseRecord z wartościami parametrów.

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

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

Źródło: jak uzyskać kod SQL do zapytania


Co to jest recordWithValues? Czy można go pobrać z DatabaseQuery lub EJBQueryImpl?
zmeda

1
Argument Record jest jednym z (Record, XMLRecord), który zawiera argumenty zapytania
Tomasz

Jeśli mam coś takiego jak Query myQuery = entityManager.createNamedQuery ("MyEntity.findMe"); myQuery.setParameter ("param1", "someValue); Jak uzyskać recordWithValues ​​z myQuery?
zmeda

Zaktualizowałem moją odpowiedź, aby uwzględnić tworzenie recordWithValues.
Tomasz

Hej, czy wiesz, jak to zrobić dla bzdur eclipseLink, które nie działa z JPA? (Nie wiem nawet, co to dokładnie jest, ale wygenerował klasy mapowania z aplikacji workbench .... Jednak nie mam EM, ale tylko usługę górnego łącza Mogę zażądać sesji, ale nie wiem o żadnym zapytaniu. używaj klas takich jak ReadAllQuery, ExpressionBuilder i Expression. Nie musisz odpowiadać, jeśli jest to zbyt niejasne (nie jestem w tym profesjonalistą, jestem przyzwyczajony do JPA). Usunę ten komentarz w ciągu najbliższych 48 godzin i spróbuję zadać jaśniejsze pytanie;)
JBA,

7

Aby wyświetlić wszystkie SQL i parametry w OpenJPA, umieść te dwa parametry w pliku persistence.xml:

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

5

Jeśli chcesz zobaczyć dokładne zapytania wraz z wartościami parametrów i zwracanymi wartościami, możesz użyć sterownika proxy jdbc. Przechwytuje wszystkie wywołania jdbc i rejestruje ich wartości. Niektóre serwery proxy:

  • log4jdbc
  • jdbcspy

Mogą również zapewniać dodatkowe funkcje, takie jak mierzenie czasu wykonywania zapytań i zbieranie statystyk.


4

Przykład z użyciem 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
Proszę wyjaśnij nieco swoją odpowiedź. Zakładam, że główną sekcją jest sekcja org.hibernate.SQL?
JackDev

2

Zrobiłem ściągawkę, która moim zdaniem może być przydatna dla innych. We wszystkich przykładach możesz usunąć format_sqlwłaściwość, jeśli chcesz zachować zarejestrowane zapytania w jednej linii (bez ładnego drukowania).

Ładnie drukuj zapytania SQL, aby ustandaryzować bez parametrów przygotowanych instrukcji i bez optymalizacji struktury logowania :

application.properties plik:

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

application.yml plik:

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

Ładnie drukowane zapytania SQL z parametrami przygotowanych instrukcji przy użyciu struktury logowania :

application.properties plik:

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

application.yml plik:

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

Ładnie drukowane zapytania SQL bez parametrów przygotowanych instrukcji za pomocą struktury logowania :

application.properties plik:

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

application.yml plik:

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

Źródło (i więcej szczegółów): https://www.baeldung.com/sql-logging-spring-boot


1

Dodatkowo, jeśli używasz WildFly / JBoss, ustaw poziom rejestrowania org.hibernate na DEBUG

Logowanie do hibernacji w WildFly


1

Inna dobra opcja, jeśli masz za dużo dziennika i chcesz umieścić tylko tymczasowy System.out.println(), możesz, w zależności od dostawcy, zrobić:

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

W naszej implementacji opartej na openjpa, nie pokazuje to parametrów jako części zapytania dla sparametryzowanego zapytania.
timwaagh

1

Jeśli używasz Spring Framework. Zmodyfikuj plik application.properties jak poniżej

#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

W przypadku Spring Boot wystarczy dodać: spring.jpa.show-sql = true do application.properties. Spowoduje to wyświetlenie zapytania, ale bez rzeczywistych parametrów (zobaczysz? Zamiast każdego parametru).


0

Podczas opracowywania eksploracyjnego i aby skupić się na rejestrowaniu debugowania SQL na określonej metodzie, którą chcę sprawdzić, dekoruję tę metodę następującymi instrukcjami rejestratora:

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 do wyprowadzenia kodu SQL (persistence.xml config):

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

-2

Jest plik o nazwie persistence.xml Naciśnij Ctrl + Shift + R i znajdź go, a następnie jest miejsce napisane coś w rodzaju showSQL.

Po prostu powiedz to jako prawdę

Nie jestem pewien, czy serwer musi być uruchomiony w trybie debugowania. Sprawdź SQL utworzone na konsoli.


to nie wystarczy, aby wyświetlić tylko parametry instrukcji sql? dla parametrów.
Ebuzer Taha KANAT

1
„Coś w rodzaju showSQL” nie jest odpowiedzią. i Ctrl + Shift + R? Zrobiłeś założenie dotyczące IDE.
8bitjunkie
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.