Не всегда понятно, почему и в какой части программы Hibernate генерирует данный SQL-запрос, особенно если мы имеем дело с кодом, который мы не написали сами.
В этом посте будет рассказано, как настроить ведение журнала запросов Hibernate и использовать его вместе с другими приемами, чтобы выяснить, почему и где в программе выполняется данный запрос.
Как выглядит журнал запросов Hibernate
Hibernate имеет встроенную регистрацию запросов, которая выглядит следующим образом:
1
2
3
4
5
|
select /* load your.package.Employee */ this_.code, ... from employee this_ where this_.employee_id=? TRACE 12-04-2014@16:06:02 BasicBinder - binding parameter [1] as [NUMBER] - 1000 |
Почему Hibernate не может регистрировать фактический запрос?
Обратите внимание, что Hibernate записывает подготовленный оператор, отправленный Hibernate драйверу JDBC, плюс его параметры. Подготовленное заявление имеет ?
вместо параметров запроса сами значения параметров записываются только под подготовленным оператором.
Это не то же самое, что фактический запрос, отправленный в базу данных, так как Hibernate не может зарегистрировать фактический запрос. Причина этого заключается в том, что Hibernate знает только о подготовленных операторах и параметрах, которые он отправляет драйверу JDBC, и именно этот драйвер будет создавать фактические запросы и затем отправлять их в базу данных.
Для создания журнала с реальными запросами необходим инструмент наподобие log4jdbc , который станет темой другого поста.
Как узнать происхождение запроса
Записанный выше запрос содержит комментарий, позволяющий в большинстве случаев определить происхождение запроса: если запрос вызван загрузкой по идентификатору, это комментарий /* load your.entity.Name */
, если это именованный запрос, то комментарий будет содержать название запроса.
Если это ленивая инициализация один ко многим, комментарий будет содержать имя класса и свойство, которое его вызвало, и т. Д.
Настройка журнала запросов Hibernate
Чтобы получить журнал запросов, в конфигурации фабрики сеансов необходимо установить следующие флаги:
1
2
3
4
5
6
7
8
9
|
< bean id = "entityManagerFactory" class = "org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" > ... < property name = "jpaProperties" > < props > < prop key = "hibernate.show_sql" >true</ prop > < prop key = "hibernate.format_sql" >true</ prop > < prop key = "hibernate.use_sql_comments" >true</ prop > </ props > </ property > |
Приведенный выше пример относится к конфигурации Spring фабрики менеджера сущностей. Это значение флагов:
-
show_sql
включает ведение журнала запросов -
format_sql
довольно печатает SQL -
use_sql_comments
добавляет пояснительный комментарий
Для регистрации параметров запроса необходима следующая log4j
или эквивалентная информация:
1
2
3
|
< logger name = "org.hibernate.type" > < level value = "trace" /> </ logger > |
Если ничего не помогает
Во многих случаях комментария, созданного с помощью use_sql_comments
, достаточно для определения источника запроса. Если этого недостаточно, то мы можем начать с определения сущности, возвращаемой запросом, на основе соответствующих имен таблиц и поместить точку останова в конструктор возвращенной сущности.
Если у сущности нет конструктора, мы можем создать его и поставить точку останова в вызове super()
:
1
2
3
4
5
6
7
|
@Entity public class Employee { public Employee() { super (); // put the breakpoint here } ... } |
Когда достигнута точка останова, перейдите к представлению отладки IDE, содержащему вызов стека программы, и пройдите по нему сверху вниз. Место, где был сделан запрос в программе, будет находиться в стеке вызовов.
Ссылка: | Отладка в спящем режиме — выяснение происхождения запроса от нашего партнера по JCG Алексея Новика в блоге The JHades Blog . |