Как вывести строку запроса с параметрами при использовании Hibernate
Возможность отображения SQL-запросов с реальными значениями в Hibernate
Здравствуйте! Я столкнулся с проблемой: возможно ли в Hibernate выводить сгенерированные SQL-запросы с реальными значениями вместо вопросительных знаков?
Если такой функционал отсутствует в API Hibernate, как бы вы предложили реализовать вывод запросов с реальными значениями? Буду признателен за любые советы или обходные пути!
5 ответ(ов)
Если вы используете Spring Boot, просто настройте это:
application.yml
logging:
level:
org.hibernate.SQL: DEBUG
org.hibernate.type: TRACE
или
application.properties
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type=TRACE
И больше ничего.
Ваши логи будут выглядеть примерно так:
2020-12-07 | DEBUG | o.h.SQL:127 - insert into Employee (id, name, title, id) values (?, ?, ?, ?)
2020-12-07 | TRACE | o.h.t.d.s.BasicBinder:64 - binding parameter [1] as [VARCHAR] - [001]
2020-12-07 | TRACE | o.h.t.d.s.BasicBinder:64 - binding parameter [2] as [VARCHAR] - [John Smith]
2020-12-07 | TRACE | o.h.t.d.s.BasicBinder:52 - binding parameter [3] as [VARCHAR] - [null]
2020-12-07 | TRACE | o.h.t.d.s.BasicBinder:64 - binding parameter [4] as [BIGINT] - [1]
Если вы используете Spring Boot 3 и/или Hibernate 6, следующая конфигурация позволит вам отображать значения параметров:
# базовый уровень логирования для всех сообщений
logging.level.org.hibernate=info
# SQL-запросы и параметры
logging.level.org.hibernate.SQL=debug
logging.level.org.hibernate.orm.jdbc.bind=trace
# Статистика и медленные запросы
logging.level.org.hibernate.stat=debug
logging.level.org.hibernate.SQL_SLOW=info
# Кэш второго уровня
logging.level.org.hibernate.cache=debug
Эта настройка позволит вам более детально видеть, что происходит в процессе выполнения SQL-запросов и работы с кэшем. Убедитесь, что вы правильно настроили уровни логирования, чтобы получить необходимую информацию.
Вот пример конфигурации для Logback (SLF4J), который может быть удобен:
<appender name="SQLROLLINGFILE">
<File>/tmp/sql.log</File>
<rollingPolicy>
<FileNamePattern>logFile.%d{yyyy-MM-dd}.log</FileNamePattern>
</rollingPolicy>
<layout>
<Pattern>%-4date | %msg %n</Pattern>
</layout>
</appender>
<logger name="org.hibernate.SQL" additivity="false">
<level value="DEBUG" />
<appender-ref ref="SQLROLLINGFILE" />
</logger>
<logger name="org.hibernate.type" additivity="false">
<level value="TRACE" />
<appender-ref ref="SQLROLLINGFILE" />
</logger>
Вывод в вашем файле sql.log
будет выглядеть следующим образом (пример):
2013-08-30 18:01:15,083 | update stepprovider set created_at=?, lastupdated_at=?, version=?, bundlelocation=?, category_id=?, customer_id=?, description=?, icon_file_id=?, name=?, shareStatus=?, spversion=?, status=?, title=?, type=?, num_used=? where id=?
2013-08-30 18:01:15,084 | binding parameter [1] as [TIMESTAMP] - 2012-07-11 09:57:32.0
2013-08-30 18:01:15,085 | binding parameter [2] as [TIMESTAMP] - Fri Aug 30 18:01:15 CEST 2013
2013-08-30 18:01:15,086 | binding parameter [3] as [INTEGER] -
2013-08-30 18:01:15,086 | binding parameter [4] as [VARCHAR] - com.mypackage.foo
2013-08-30 18:01:15,087 | binding parameter [5] as [VARCHAR] -
2013-08-30 18:01:15,087 | binding parameter [6] as [VARCHAR] -
2013-08-30 18:01:15,087 | binding parameter [7] as [VARCHAR] - TODO
2013-08-30 18:01:15,087 | binding parameter [8] as [VARCHAR] -
2013-08-30 18:01:15,088 | binding parameter [9] as [VARCHAR] - [email protected]
2013-08-30 18:01:15,088 | binding parameter [10] as [VARCHAR] - PRIVATE
2013-08-30 18:01:15,088 | binding parameter [11] as [VARCHAR] - 1.0
2013-08-30 18:01:15,088 | binding parameter [12] as [VARCHAR] - 32
2013-08-30 18:01:15,088 | binding parameter [13] as [VARCHAR] - MatchingStep
2013-08-30 18:01:15,089 | binding parameter [14] as [VARCHAR] -
2013-08-30 18:01:15,089 | binding parameter [15] as [INTEGER] - 0
2013-08-30 18:01:15,089 | binding parameter [16] as [VARCHAR] - 053c2e65-5d51-4c09-85f3-2281a1024f64
Эта конфигурация позволяет логировать SQL-запросы и параметры, к которым они привязаны, что может быть полезно для отладки и мониторинга работы приложения.
Для активации отображения SQL-запросов и их формата в Hibernate, вам необходимо внести изменения в файл hibernate.cfg.xml
. Добавьте или измените следующие строки:
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<property name="use_sql_comments">true</property>
Кроме того, чтобы настроить логирование с помощью log4j, вам потребуется добавить соответствующие записи в файл log4j.properties
. Вот пример конфигурации:
log4j.logger.org.hibernate=INFO, hb
log4j.logger.org.hibernate.SQL=DEBUG
log4j.logger.org.hibernate.type=TRACE
log4j.appender.hb=org.apache.log4j.ConsoleAppender
log4j.appender.hb.layout=org.apache.log4j.PatternLayout
Эта настройка будет отображать SQL-запросы в консоли, а также позволит вам видеть более детальную информацию о типах данных, которые обрабатываются Hibernate. Убедитесь, что log4j подключен к вашему проекту, чтобы эти настройки заработали.
Log4JDBC — это отличное решение, которое выводит точный SQL-запрос, отправляемый в базу данных, с подставленными параметрами, в отличие от самого популярного ответа здесь, который этого не делает. Одним из больших удобств является то, что вы можете просто скопировать SQL-продолжение и выполнить его в своей фронтальной части базы данных, не внося изменений.
Последний также выводит табличное представление результатов запросов.
Пример вывода, показывающий сгенерированный SQL с подставленными параметрами, а также таблицу результирующего набора из запроса:
5. insert into ENQUIRY_APPLICANT_DETAILS (ID, INCLUDED_IN_QUOTE, APPLICANT_ID, TERRITORY_ID, ENQUIRY_ID, ELIGIBLE_FOR_COVER) values (7, 1, 11, 1, 2, 0)
10 Oct 2013 16:21:22 4953 [main] INFO jdbc.resultsettable - |---|--------|--------|-----------|----------|---------|-------|
10 Oct 2013 16:21:22 4953 [main] INFO jdbc.resultsettable - |ID |CREATED |DELETED |CODESET_ID |NAME |POSITION |PREFIX |
10 Oct 2013 16:21:22 4953 [main] INFO jdbc.resultsettable - |---|--------|--------|-----------|----------|---------|-------|
10 Oct 2013 16:21:22 4953 [main] INFO jdbc.resultsettable - |2 |null |null |1 |Country 2 |1 |60 |
10 Oct 2013 16:21:22 4953 [main] INFO jdbc.resultsettable - |---|--------|--------|-----------|----------|---------|-------|
Обновление 2016 года
В последнее время я использую log4jdbc-log4j2
(https://code.google.com/archive/p/log4jdbc-log4j2/) с SLF4j и logback
. Необходимые зависимости Maven для моей конфигурации выглядят следующим образом:
<dependency>
<groupId>org.bgee.log4jdbc-log4j2</groupId>
<artifactId>log4jdbc-log4j2-jdbc4.1</artifactId>
<version>1.16</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
Классы драйвера и URL базы данных выглядят так:
database.driver.class=net.sf.log4jdbc.sql.jdbcapi.DriverSpy
database.url=jdbc:log4jdbc:hsqldb:mem:db_name #Hsql
#database.url=jdbc:log4jdbc:mysql://localhost:3306/db_name
Мой файл конфигурации logback.xml
выглядит следующим образом: он выводит все SQL-запросы с параметрами и таблицы результирующего набора для всех запросов.
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<logger name="jdbc.audit" level="ERROR" />
<logger name="jdbc.connection" level="ERROR" />
<logger name="jdbc.sqltiming" level="ERROR" />
<logger name="jdbc.resultset" level="ERROR" />
<!-- РАСКОММЕНТУЙТЕ НИЖЕ, ЧТОБЫ СКРЫТЬ ВЫВОД ТАБЛИЦЫ РЕЗУЛЬТАТОВ -->
<!--<logger name="jdbc.resultsettable" level="ERROR" /> -->
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
Наконец, я создал файл с именем log4jdbc.log4j2.properties
в корне classpath, например, src/test/resources
или src/main/resources
в проекте Maven. Этот файл имеет одну строку:
log4jdbc.spylogdelegator.name=net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator
Это будет зависеть от вашего журнала. Более подробную информацию смотрите в документации по адресу https://code.google.com/archive/p/log4jdbc-log4j2.
Пример вывода:
10:44:29.400 [main] DEBUG jdbc.sqlonly - org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:70)
5. select memberrole0_.member_id as member_i2_12_0_, memberrole0_.id as id1_12_0_, memberrole0_.id
as id1_12_1_, memberrole0_.member_id as member_i2_12_1_, memberrole0_.role_id as role_id3_12_1_,
role1_.id as id1_17_2_, role1_.name as name2_17_2_ from member_roles memberrole0_ left outer
join roles role1_ on memberrole0_.role_id=role1_.id where memberrole0_.member_id=104
10:44:29.402 [main] INFO jdbc.resultsettable -
|----------|---|---|----------|--------|---|-----|
|member_id |id |id |member_id |role_id |id |name |
|----------|---|---|----------|--------|---|-----|
|----------|---|---|----------|--------|---|-----|
Как исправить ошибку Hibernate "объект ссылается на несохраненный временный экземпляр - сохраните временный экземпляр перед сбросом"
JPA JoinColumn против mappedBy: в чем разница?
В чем разница между JPA и Hibernate? [закрыт]
Возможные значения конфигурации hbm2ddl.auto в Hibernate и их назначение
Как зарегистрировать SQL-запросы в Spring Boot?