Как просмотреть SQL-запросы, выданные JPA?


155

Когда мой код выдает вызов, как это:

entityManager.find(Customer.class, customerID);

Как я могу увидеть SQL-запрос для этого вызова? Предполагая, что у меня нет доступа к серверу базы данных для профилирования / мониторинга вызовов, есть ли способ регистрировать или просматривать в моей IDE соответствующие запросы SQL, выданные вызовами JPA? Я иду против SQL Server 2008 R2 с использованием драйвера jTDS.


8
Что такое провайдер JPA? Я считаю, что этот параметр зависит от поставщика.
btiernay

@ Сажи, пожалуйста, не могли бы вы пометить ответ axtavt как принятый, чтобы он направил посетителей на ваш вопрос прямо к этому ответу?
8bitjunkie

Ответы:


332

Параметры ведения журнала зависят от поставщика. Вы должны знать, какую реализацию JPA вы используете.

  • Hibernate ( см. Здесь ):

    <property name = "hibernate.show_sql" value = "true" />
  • EclipseLink ( см. Здесь ):

    <property name="eclipselink.logging.level" value="FINE"/>
  • OpenJPA ( см. Здесь ):

    <property name="openjpa.Log" value="DefaultLevel=WARN,Runtime=INFO,Tool=INFO,SQL=TRACE"/>
  • DataNucleus ( см. Здесь ):

    Установите категорию журнала DataNucleus.Datastore.Nativeна уровень, например DEBUG.


4
@ Сажи: Вы должны поставить галочку в этом ответе, чтобы указать, что это принятый ответ. Это прекрасно работает для меня, используя Hibernate. Если вы одобрите этот ответ, вы и ответчик получите больше очков и больше разрешений на stackoverflow.com.
LS

57
Вы поместите эту строку в свой файл persistence.xml для любого тела, которое является пьяным. Это было бы под узлом <properties> ... Извините, если это очевидно, я просто запутался, где поставить его сам.
SoftwareSavant

5
При использовании Hibernate и log4j вы также можете установить для регистратора «org.hibernate.SQL» значение DEBUG ( javalobby.org/java/forums/t44119.html )
MosheElisha

Кроме того, кажется, что узел <properties> должен быть ниже всего остального внутри <persistence-unit>. <3 XML.
Том Сперлинг,

1
Где должны быть установлены эти свойства?
Алекс Уорден

34

Кроме того, если вы используете EclipseLink и хотите вывести значения параметров SQL, вы можете добавить это свойство в свой файл persistence.xml:

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

Есть ли альтернатива для получения значений привязки в intellij?
Виниций М

15

Если вы используете hibernate и logback в качестве регистратора, вы можете использовать следующее (показывает только привязки, а не результаты):

<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 печатает запрос

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

org.hibernate.type = TRACE печатает привязки и обычно результаты, которые будут подавлены через пользовательский фильтр

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

Вам нужна зависимость 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

В EclipseLink для получения SQL для конкретного запроса во время выполнения вы можете использовать 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();

Этот SQL будет содержать? для параметров. Для перевода SQL с аргументами вам необходим DatabaseRecord со значениями параметров.

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

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

Источник: Как получить SQL для запроса


Что такое recordWithValues? Можно ли получить его из DatabaseQuery или EJBQueryImpl?
zmeda

1
Аргумент Record является одним из (Record, XMLRecord), который содержит аргументы запроса
Томаш

Если у меня есть что-то вроде Query myQuery = entityManager.createNamedQuery ("MyEntity.findMe"); myQuery.setParameter ("param1", "someValue); как получить recordWithValues ​​из myQuery?
zmeda

Обновлен мой ответ, чтобы включить создание recordWithValues.
Томаш

Эй, вы знаете, как это сделать для дерьма eclipseLink, которое не работает с JPA? (Я даже не знаю, что именно, но он сгенерировал классы отображения из приложения рабочей среды .... Однако у меня нет EM, а есть только служба toplink, я могу запросить сеанс, но он не знает ни одного запроса. используйте классы, такие как ReadAllQuery, ExpressionBuilder и Expression. Вам не нужно отвечать, если это слишком неясно (я не профессионал в этом, я привык к JPA), я удалю этот комментарий в течение следующих 48 часов и попытаюсь задать более ясный вопрос;)
JBA

7

Чтобы просмотреть все SQL и параметры в OpenJPA, поместите эти два параметра в файл persistence.xml:

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

5

Если вы хотите видеть точные запросы вместе со значениями параметров и возвращаемыми значениями, вы можете использовать прокси-драйвер jdbc. Он будет перехватывать все вызовы jdbc и записывать их значения. Некоторые прокси:

  • log4jdbc
  • jdbcspy

Они также могут предоставлять некоторые дополнительные функции, такие как измерение времени выполнения запросов и сбор статистики.


4

Пример использования 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
Пожалуйста, объясните свой ответ немного больше. Я предполагаю, что основным разделом является раздел org.hibernate.SQL?
ДжекДев

2

Я сделал шпаргалку, я думаю, что может быть полезным для других. Во всех примерах вы можете удалить это format_sqlсвойство, если хотите сохранить зарегистрированные запросы в одной строке (без красивой печати).

Довольно распечатывать SQL-запросы без параметров подготовленных операторов и без оптимизации каркаса журналирования :

application.properties файл:

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

application.yml файл:

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

Довольно распечатать SQL-запросы с параметрами подготовленных операторов с использованием каркаса журналирования :

application.properties файл:

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

application.yml файл:

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

Довольно распечатать SQL-запросы без параметров подготовленных операторов с использованием каркаса журналирования :

application.properties файл:

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

application.yml файл:

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

Источник (и более подробная информация): https://www.baeldung.com/sql-logging-spring-boot


1

Кроме того, если вы используете WildFly / JBoss, установите для уровня ведения журнала org.hibernate значение DEBUG.

Вход в спящий режим в WildFly


1

Еще один хороший вариант, если у вас слишком много журналов и вы хотите поместить их только как временные System.out.println(), вы можете, в зависимости от того, что делает ваш провайдер:

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

В нашей реализации на основе openjpa это не показывает параметры как часть запроса для параметризованного запроса.
Тимвааг

1

Если вы используете Spring Framework. Измените файл application.properties, как показано ниже

#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

Я не использую Hibernate. AFAIK, просто старый JPA. showSQL выглядит как свойство Hibernate. Будет ли это работать в моем случае?
Sajee

Похоже, ответ нет. Я не вижу SQL в журналах.
Sajee

1
Sajee, как вы объявляете свойства в вашем файле persistence.xml?
Gondim

0

С помощью Spring Boot просто добавьте: spring.jpa.show-sql = true в application.properties. Это покажет запрос, но без фактических параметров (вы увидите? Вместо каждого параметра).


0

Во время исследовательской разработки и для того, чтобы сфокусировать ведение журнала отладки SQL на конкретном методе, который я хочу проверить, я украсил этот метод следующими инструкциями 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 для вывода SQL (config persistence.xml):

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

-2

Там есть файл с именем persistence.xml. Нажмите Ctrl + Shift + R и найдите его, затем есть место, где написано что-то вроде showSQL.

Просто скажи это как правда

Я не уверен, должен ли сервер быть запущен в режиме отладки. Проверьте SQL, созданные на консоли.


это не достаточно, чтобы показать параметры SQL-оператор только показывает? для параметров.
Эбузер Таха КАНАТ

1
«Что-то вроде showSQL» не является ответом. и Ctrl + Shift + R? Вы сделали предположение об IDE.
8bitjunkie
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.