Не всегда понятно, почему и в какой части программы 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
|
@Entitypublic class Employee { public Employee() { super(); // put the breakpoint here } ...} |
Когда достигнута точка останова, перейдите к представлению отладки IDE, содержащему вызов стека программы, и пройдите по нему сверху вниз. Место, где был сделан запрос в программе, будет находиться в стеке вызовов.
| Ссылка: | Отладка в спящем режиме — выяснение происхождения запроса от нашего партнера по JCG Алексея Новика в блоге The JHades Blog . |