如果我們對休眠配置進行概述,則應啟用兩個屬性hibernate.format_sql和hibernate.use_sql_comments,以通過控制臺打印執行的sql代碼。
這是一個好的開始,但是似乎我們需要更多信息來準確診斷性能,例如連接事件,查詢返回的數據或參數綁定( 休眠顯示帶問號?的參數值)。 因此,我們需要另一種方法來檢查生成的sql 。 Log4jdbc是一個jdbc驅動程序,可以記錄sql / jdbc調用。 實際上, log4jdbc是代理模式的實現,它將自動加載流行的jdbc驅動程序( Oracle,Derby,MySql,PostgreSql,H2,Hsqldb等),攔截調用,記錄信息,然后將數據發送到“ 間諜 ”驅動程序。
在log4jdbc中 ,根據要監視的數據,可以使用5個記錄器:
- jdbc.sqlonly :使用綁定參數替換為綁定數據來記錄執行的sql 。
- jdbc.sqltiming :記錄執行一條SQL所花費的時間。
- jdbc.audit :記錄除ResultSets之外的所有jdbc調用。
- jdbc.resultset :與jdbc.audit以及ResultsSets相同。
- jdbc.connection :記錄打開和關閉連接事件。
在本文中,我們將了解如何配置log4jdbc-remix ,這是log4jdbc的分支 ,除了繼承log4jdbc功能之外,還可以讓我們:
- jdbc.resultsettable :以表格式記錄結果集。
- 將其配置為數據源。
- 在Maven存儲庫中可用(在Maven存儲庫中不存在log4jdbc )。
在此示例中,我們將使用由JPA Spring模板創建的項目,該項目包含兩個與一對多關系相關聯的實體Order和Item ,以及一個執行某些數據庫操作的測試。
首先要做的是將log4jdb-remix和slf4j-log4j12依賴項添加到項目中:
<dependency><groupId>org.slf4j<groupId><artifactId>slf4j-log4j12<artifactId><version>1.6.4<version><dependency><dependency><groupId>org.lazyluke<groupId><artifactId>log4jdbc-remix<artifactId><version>0.2.7<version><dependency>
接下來要做的是配置活動記錄器。 根據我們要監視的數據,我們激活所需的記錄器。 作為示例,讓我們配置log4j.xml,以便以表格式打印結果集,并顯示執行每個查詢所花費的時間。
<?xml version='1.0' encoding='UTF-8' ?><!DOCTYPE log4j:configuration SYSTEM 'log4j.dtd'><log4j:configuration xmlns:log4j='http:jakarta.apache.orglog4j'><appender name='console-log4jdbc' class='org.apache.log4j.ConsoleAppender'><param name='Target' value='System.out' ><layout class='org.apache.log4j.PatternLayout'><param name='ConversionPattern' value='%m%n' ><layout><appender><!-- <logger name='jdbc.sqlonly' additivity='false'> --><!-- <level value='debug' > --><!-- <appender-ref ref='console-log4jdbc' > --><!-- <logger> --><logger name='jdbc.sqltiming' additivity='false'><level value='info' ><appender-ref ref='console-log4jdbc' ><logger><!-- <logger name='jdbc.connection' additivity='false'> --><!-- <level value='info' > --><!-- <appender-ref ref='console-log4jdbc' > --><!-- <logger> --><!-- log4jdbc option log the jdbc results as a table --><logger name='jdbc.resultsettable' additivity='false'><level value='info' ><appender-ref ref='console-log4jdbc' ><logger><log4j:configuration>
配置記錄器后,運行測試并檢查輸出
create table Item (id bigint generated by default as identity, price double not null, product varchar(255), quantity integer not null, order_id bigint, primary key (id)) {executed in 10 msec}create table T_ORDER (id bigint generated by default as identity, customer varchar(255), primary key (id)) {executed in 1 msec}alter table Item add constraint FK22EF339F325255 foreign key (order_id) references T_ORDER {executed in 11 msec}insert into T_ORDER (id, customer) values (null, NULL) {executed in 1 msec}insert into Item (id, order_id, price, product, quantity) values (null, NULL, 0.0, NULL, 0) {executed in 0 msec}batching 1 statements: 0: update Item set ORDER_ID=1 where id=1 {executed in 2 msec}insert into T_ORDER (id, customer) values (null, NULL) {executed in 0 msec}insert into Item (id, order_id, price, product, quantity) values (null, NULL, 0.0, NULL, 0) {executed in 0 msec}batching 1 statements: 0: update Item set ORDER_ID=2 where id=2 {executed in 0 msec}select order0_.id as id1_0_, order0_.customer as customer1_0_ from T_ORDER order0_ where order0_.id=2 {executed in 0 msec}|---------|---------||ID |CUSTOMER ||---------|---------||[unread] |null ||---------|---------|select items0_.ORDER_ID as ORDER5_1_2_, items0_.id as id2_, items0_.id as id0_1_, items0_.order_id as order5_0_1_, items0_.price as price0_1_, items0_.product as product0_1_, items0_.quantity as quantity0_1_, order1_.id as id1_0_, order1_.customer as customer1_0_ from Item items0_ left outer join T_ORDER order1_ on items0_.order_id=order1_.id where items0_.ORDER_ID=2 {executed in 0 msec}|---------|---|---|---------|------|--------|---------|---|---------||ORDER_ID |ID |ID |ORDER_ID |PRICE |PRODUCT |QUANTITY |ID |CUSTOMER ||---------|---|---|---------|------|--------|---------|---|---------||2 |2 |2 |2 |0.0 |null |0 |2 |[unread] ||---------|---|---|---------|------|--------|---------|---|---------|insert into T_ORDER (id, customer) values (null, NULL) {executed in 0 msec}insert into Item (id, order_id, price, product, quantity) values (null, NULL, 0.0, 'foo', 0) {executed in 0 msec}batching 1 statements: 0: update Item set ORDER_ID=3 where id=3 {executed in 0 msec}select order0_.id as id1_, order0_.customer as customer1_ from T_ORDER order0_ inner join Item items1_ on order0_.id=items1_.ORDER_ID where items1_.product='foo' limit 2 {executed in 6 msec}|---|---------||ID |CUSTOMER ||---|---------||3 |null ||---|---------|select items0_.ORDER_ID as ORDER5_1_2_, items0_.id as id2_, items0_.id as id0_1_, items0_.order_id as order5_0_1_, items0_.price as price0_1_, items0_.product as product0_1_, items0_.quantity as quantity0_1_, order1_.id as id1_0_, order1_.customer as customer1_0_ from Item items0_ left outer join T_ORDER order1_ on items0_.order_id=order1_.id where items0_.ORDER_ID=3 {executed in 0 msec}|---------|---|---|---------|------|--------|---------|---|---------||ORDER_ID |ID |ID |ORDER_ID |PRICE |PRODUCT |QUANTITY |ID |CUSTOMER ||---------|---|---|---------|------|--------|---------|---|---------||3 |3 |3 |3 |0.0 |foo |0 |3 |[unread] ||---------|---|---|---------|------|--------|---------|---|---------|
輸出以一種時尚的格式打印,查詢包含綁定參數(不是問號(?)),并且還通知了處理時間。
請注意,記錄或多或少的信息僅是配置日志的問題。 此外,根據日志級別,將在每種情況下提供或多或少的信息。 如果在DEBUG中配置了logger,則將包括執行該sql的類名和行號(如果有)。 在INFO中將僅包含sql ,最后包含ERROR ,如果發生任何SQLException則顯示堆棧跟蹤。
優化休眠應用程序可能意味著接觸到應用程序的許多部分( JVM配置,數據庫引擎,網絡等),但是要注意的一個非常重要的方面是發送到RDBMS的查詢的數量(例如N + 1問題),以及從數據庫中檢索到的數據量(投影問題)和log4jdbc-remix完全適合于此目的。
作為最后一點,log4jdbc( - 混音 )是一個JDBC記錄,所以沒有必要只在Hibernate應用程序使用,可以與任何框架一起使用,使用一個數據源 。
希望該庫對您有所幫助。
保持學習,
下載代碼
參考:在One Jar To Rulem All博客中,我們的JCG合作伙伴 Alex Soto 使用Log4jdbc記錄了JDBC操作 。
翻譯自: https://www.javacodegeeks.com/2012/05/log-jdbc-operations-with-log4jdbc.html