Статьи

Spring / Hibernate улучшено ведение журнала SQL с log4jdbc

Hibernate обеспечивает ведение журнала SQL из коробки, но такое ведение журнала показывает только подготовленные операторы, а не фактические запросы SQL, отправленные в базу данных.

Он также не регистрирует время выполнения каждого запроса, что полезно для устранения неполадок производительности. В этом сообщении будет рассказано, как настроить ведение журнала запросов Hibernate, а затем сравнить его с ведением журнала, которое можно получить с помощью log4jdbc .

Функциональность ведения журнала запросов Hibernate

Hibernate не регистрирует реальные запросы SQL, отправленные в базу данных. Это связано с тем, что Hibernate взаимодействует с базой данных через драйвер JDBC, которому он отправляет подготовленные операторы, но не фактические запросы.

Таким образом, Hibernate может регистрировать только подготовленные операторы и значения их параметров привязки, но не сами запросы SQL.

Вот как выглядит запрос при входе в 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 выполняет этот SQL-запрос? как настроить этот тип регистрации.

Использование log4jdbc

Для разработчика полезно иметь возможность скопировать запрос из журнала и выполнить запрос непосредственно в клиенте SQL, но как переменные-заполнители ? сделать это невыполнимым.

Log4jdbc в инструмент с открытым исходным кодом, который позволяет делать именно это, и многое другое. Log4jdbc — это шпионский драйвер, который оборачивается вокруг реального драйвера JDBC, регистрируя запросы по мере их прохождения.

Версия, на которую ссылается этот пост, обеспечивает интеграцию с Spring, в отличие от нескольких других форков log4jdbc.

Настройка log4jdbc

Сначала включите библиотеку log4jdbc-remix в ваш файл pom.xml. Эта библиотека является веткой оригинального log4jdbc:

1
2
3
4
5
<dependency>
    <groupId>org.lazyluke</groupId>
    <artifactId>log4jdbc-remix</artifactId
    <version>0.2.7</version>
</dependency>

Затем найдите в конфигурации Spring определение источника данных. Например, при использовании элемента поиска JNDI вот как выглядит источник данных:

1
2
<jee:jndi-lookup id="dataSource"
    jndi-name="java:comp/env/jdbc/some-db" />

Найдя определение источника данных, переименуйте его в следующее имя:

1
2
<jee:jndi-lookup id="dataSourceSpied"
    jndi-name="java:comp/env/jdbc/some-db" />

Затем определите новый источник данных log4jdbc, который обертывает реальный источник данных, и дайте ему оригинальное имя:

01
02
03
04
05
06
07
08
09
10
<bean id="dataSource" class="net.sf.log4jdbc.Log4jdbcProxyDataSource" >        
     <constructor-arg ref="dataSourceSpied" />        
     <property name="logFormatter">                   
         <bean class="net.sf.log4jdbc.tools.Log4JdbcCustomFormatter" >
             <property name="loggingType" value="SINGLE_LINE" />
             <property name="margin" value="19" />  
             <property name="sqlPrefix" value="SQL:::" />           
         </bean>           
     </property>    
</bean >

При такой конфигурации ведение журнала запросов уже должно работать. Можно настроить уровень регистрации нескольких доступных регистраторов log4jdbc.

Оригинальная документация log4jdbc предоставляет дополнительную информацию о доступных регистраторах:

  • jdbc.sqlonly : jdbc.sqlonly только SQL
  • jdbc.sqltiming : jdbc.sqltiming SQL, пост-выполнение, включая статистику выполнения по времени
  • jdbc.audit : jdbc.audit ВСЕ вызовы JDBC за исключением ResultSets
  • jdbc.resultset : все обращения к объектам ResultSet регистрируются
  • jdbc.connection : jdbc.connection соединения, открывают и закрывают события

Регистратор jdbc.audit особенно полезен для проверки объема транзакций, так как он регистрирует события начала / фиксации / отката транзакции базы данных.

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
<logger name="jdbc.sqltiming" additivity ="false">            
     <level value="info" />               
 </logger
 <logger name="jdbc.resultset" additivity ="false">             
     <level value="error" />       
 </logger
 <logger name="jdbc.audit" additivity ="false">
     <level value="error" />       
 </logger>  
 <logger name="jdbc.sqlonly" additivity ="false">             
     <level value="error" />       
 </logger>  
 <logger name="jdbc.resultsettable" additivity ="false">          
     <level value="error" />      
 </logger>          
 <logger name="jdbc.connection" additivity ="false">             
     <level value="error" />       
 </logger
 <logger name="jdbc.resultsettable" additivity ="false">           
     <level value="error" />       
 </logger>

Вывод

Использование log4jdbc просто выполняет некоторую начальную настройку, но как только она установлена, ее действительно удобно иметь. Наличие настоящего журнала запросов также полезно для устранения неполадок производительности, как будет описано в следующем посте.

Ссылка: Spring / Hibernate улучшил ведение журнала SQL с помощью log4jdbc от нашего партнера по JCG Алексея Новика в блоге The JHades Blog .