- 前言
- log4jdbc簡介
- 特性
- 使用
- 0 jar包的選擇
- 1 日志系統的選擇
- 2 更改DriverClass
- 3 prepend jdbcUrl屬性
- 4 建立你的日志系統
- 5 修改debug選項可選
- 實戰
- 0 純JDBClog4j
- 00 jar包
- 01 配置檔案
- 02 測試
- 1 DataSourcec3p0
- 10 jar包
- 11 配置檔案
- 12 測試
- 0 純JDBClog4j
- 聲明
0 前言
使用java進行資料庫操作時最痛苦的莫過于拼接SQL語句。在實際運作時往往需要檢視實際生成的SQL語句和實際傳入的參數,或許還會有檢視SQL執行時間等的需求。
無論原生JDBC、dbutils、mybatis還是hibernate,使用log4j等日志架構可以看到生成的SQL,但是占位符和參數總是分開列印的。實在是不太友好。顯示如下的效果:
log4jdbc能很好的解決上述問題。使用log4jdbc之後的效果如下:
1 log4jdbc簡介
沒有什麼比官網對它的介紹更加貼切了:
log4jdbc is a Java JDBC driver that can log SQL and/or JDBC calls (and optionally SQL timing information) for other JDBC drivers using the Simple Logging Facade For Java (SLF4J) logging system.
但是,衆所周知googlecode在國内的通路問題……
官網的News一欄有如下消息:
2015-03-30: Due to Google Code shutting down soon, log4jdbc has moved to github at 2015-03-30: Due to Google Code shutting down soon, log4jdbc has moved to github at https://github.com/arthurblake/log4jdbc
2 特性
- 完全支援JDBC3和JDBC4
- 配置簡單,一般情況下你隻需要将你的DriverClass改為:net.sf.log4jdbc.DriverSpy,并在你的jdbcUrl之前拼接jdbc:log4
- 自動将占位符(?)替換為實際的參數
- 能夠及時友善地顯示SQL的實際執行時間
- 顯示SQL Connection的數量的資訊
- 能在JDK1.4+和SLF4J1.X上和大多數常見的JDBC驅動協同工作
- open source
3 使用
以下多數資訊來自于官網
3.0 jar包的選擇
JDK Version | jar file |
---|---|
JDK 1.4 or 1.5 | JDBC 3 version of log4jdbc |
JDK 1.6 or 1.7 | JDBC 4 version of log4jdbc |
不了解 JDBC3 JDBC4?
3.1 日志系統的選擇
log4jdbc 使用Simple Logging Facade for Java (SLF4j) 作為日志系統,(SLF4J)是一個簡單靈活的日志抽象層,可以友善的在以下日志系統之間切換:下載下傳 SLF4j,你将需要slf4j-api-1.5.0.jar和你實際所用的日志系統的jar包,或許還會有一個适配的中間插件jar包(取決于你使用的實際日志系統)。
- Log4j
- java.util logging in JDK 1.4
- logback
- Jakarta Commons Logging
3.2 更改DriverClass
log4jdbc “spy” driver 将會嘗試着加載以下驅動:
Driver Class | Database Type |
---|---|
oracle.jdbc.driver.OracleDriver | Older Oracle Driver |
oracle.jdbc.OracleDriver | Newer Oracle Driver |
com.sybase.jdbc2.jdbc.SybDriver | Sybase |
net.sourceforge.jtds.jdbc.Driver | jTDS SQL Server & Sybase driver |
com.microsoft.jdbc.sqlserver.SQLServerDriver | Microsoft SQL Server 2000 driver |
com.microsoft.sqlserver.jdbc.SQLServerDriver | Microsoft SQL Server 2005 driver |
weblogic.jdbc.sqlserver.SQLServerDriver | Weblogic SQL Server driver |
com.informix.jdbc.IfxDriver | Informix |
org.apache.derby.jdbc.ClientDriver | Apache Derby client/server driver, aka the Java DB |
org.apache.derby.jdbc.EmbeddedDriver | Apache Derby embedded driver, aka the Java DB |
com.mysql.jdbc.Driver | MySQL |
org.postgresql.Driver | PostgresSQL |
org.hsqldb.jdbcDriver | HSQLDB pure Java database |
org.h2.Driver | H2 pure Java database |
注意: 如果你要使用一個不在上表中的Driver,請提供log4jdbc.drivers配置,多個之間用逗号分隔,不帶空格。
3.3 prepend jdbcUrl屬性
例如:
你的url為: url= jdbc:mysql://localhost:3306/mvn
應該改為: url= jdbc:log4jdbc:mysql://localhost:3306/mvn
3.4 建立你的日志系統
log4jdbc使用5種logger:
logger | 描述 | since |
---|---|---|
jdbc.sqlonly | 僅僅記錄 SQL 語句,會将占位符替換為實際的參數 | 1.0 |
jdbc.sqltiming | 包含 SQL 語句實際的執行時間 | 1.0 |
jdbc.audit | 除了 ResultSet 之外的所有JDBC調用資訊,篇幅較長 | 1.0 |
jdbc.resultset | 包含 ResultSet 的資訊,輸出篇幅較長 | 1.0 |
jdbc.connection | 輸出了 Connection 的 open、close 等資訊 | 1.2alpha1 |
此外還有個叫 log4jdbc.debug 的 logger,用于log4jdbc的内部調試,會輸出 log4jdbc spy 加載驅動的時的資訊,如driver found 或 not found 等資訊。
3.5 修改debug選項–可選
可以在類路徑下提供一個名為 log4jdbc.properties 的配置檔案,用以修改一些預設的debug屬性。
其常用屬性如下(來自于 官網 文檔):
property | default | description | since |
---|---|---|---|
log4jdbc.drivers | log4jdbc 加載的一個或多個驅動的全類名。如果有多個,每個之間用逗号分隔(不帶空格).對應常見的 JDBC drivers 此選項不是必須的。但是如果需要多個 driver ,需要配置該選項。 | 1.0 | |
log4jdbc.auto.load.popular.drivers | true | 自動加載常用的jdbc driver,如果設定為false,則必須提供 log4jdbc.drivers 屬性。 | 1.2beta2 |
log4jdbc.debug.stack.prefix | The partial (or full) package prefix for the package name of your application. The call stack will be searched down to the first occurrence of a class that has the matching prefix. If this is not set, the actual class that called into log4jdbc is used in the debug output (in many cases this will be a connection pool class.) For example, setting a system property such as this: -Dlog4jdbc.debug.stack.prefix=com.mycompany.myapp Would cause the call stack to be searched for the first call that came from code in the com.mycompany.myapp package or below, thus if all of your sql generating code was in code located in the com.mycompany.myapp package or any subpackages, this would be printed in the debug information, rather than the package name for a connection pool, object relational system, etc. | 1.0 | |
log4jdbc.sqltiming.warn.threshold | 毫秒值.執行時間超過該值的SQL語句将被記錄為warn級别. | 1.1beta1 | |
log4jdbc.sqltiming.error.threshold | 毫秒值.執行時間超過該值的SQL語句将被記錄為error級别. | 1.1beta1 | |
log4jdbc.dump.booleanastruefalse | false | 當該值為 false 時,boolean 值顯示為 0 和 1 ,為 true 時 boolean 值顯示為 true 和 false | 1.2alpha1 |
log4jdbc.dump.sql.maxlinelength | 90 | SQL 分行的最大值 | 1.2alpha1 |
log4jdbc.dump.fulldebugstacktrace | false | 設定為 true 将會輸出大篇幅的 debug資訊 | 1.2alpha1 |
log4jdbc.dump.sql.select | true | 是否輸出 select 語句 | 1.2alpha1 |
log4jdbc.dump.sql.insert | true | 是否輸出 insert 語句 | 1.2alpha1 |
log4jdbc.dump.sql.delete | true | 是否輸出 delete 語句 | 1.2alpha1 |
log4jdbc.dump.sql.update | true | 是否輸出 update 語句 | 1.2alpha1 |
log4jdbc.dump.sql.create | true | 是否輸出 create 語句 | 1.2alpha1 |
log4jdbc.dump.sql.addsemicolon | false | 是否在 SQL 的行末添加一個分号 | 1.2alpha1 |
log4jdbc.statement.warn | false | Set this to true to display warnings (Why would you care?) in the log when Statements are used in the log. NOTE, this was always true in releases previous to 1.2alpha2. It is false by default starting with release 1.2 alpha 2. | 1.2alpha2 |
log4jdbc.trim.sql | true | Set this to false to not trim the logged SQL. (Previous versions always trimmed the SQL.) | 1.2beta2 |
log4jdbc.trim.sql.extrablanklines | true | Set this to false to not trim extra blank lines in the logged SQL (by default, when more than one blank line in a row occurs, the contiguous lines are collapsed to just one blank line.) (Previous versions didn’t trim extra blank lines at all.) | 1.2 |
log4jdbc.suppress.generated.keys.exception | false | Set to true to ignore any exception produced by the method, Statement.getGeneratedKeys() (Useful for using log4jdbc with Coldfusion.) | 1.2beta2 |
4 實戰
4.0 純JDBC–log4j
4.0.0 jar包
maven 依賴
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.googlecode.log4jdbc</groupId>
<artifactId>log4jdbc</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.35</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.0</version>
</dependency>
</dependencies>
4.0.1 配置檔案
- log4j.properties
log4j.logger.jdbc.sqlonly=OFF log4j.logger.jdbc.sqltiming=INFO log4j.logger.jdbc.audit=OFF log4j.logger.jdbc.resultset=OFF log4j.logger.jdbc.connection=OFF log4j.logger.jdbc.sqlonly=console log4j.appender.console=org.apache.log4j.ConsoleAppender log4j.appender.console.layout=org.apache.log4j.PatternLayout log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss.SSS} %m%n%n #log4j.logger.jdbc.sqltiming=INFO,console #log4j.logger.jdbc.connection=INFO,console log4j.rootLogger=DEBUG, console
- dbconfig.properties
java url:jdbc:log4jdbc:mysql://localhost:3306/mvn driverClassName:net.sf.log4jdbc.DriverSpy username:root password:root
- log4jdbc.properties
log4jdbc.debug.stack.prefix=software_test.log4jdbc log4jdbc.drivers=com.mysql.jdbc.Driver log4jdbc.auto.load.popular.drivers=true log4jdbc.statement.warn=true log4jdbc.sqltiming.warn.threshold= log4jdbc.sqltiming.error.threshold= log4jdbc.dump.booleanastruefalse=true log4jdbc.dump.sql.maxlinelength= log4jdbc.dump.fulldebugstacktrace=false log4jdbc.dump.sql.select=true log4jdbc.dump.sql.insert=true log4jdbc.dump.sql.delete=true log4jdbc.dump.sql.update=true log4jdbc.dump.sql.create=true log4jdbc.dump.sql.addsemicolon=false log4jdbc.trim.sql=true log4jdbc.trim.sql.extrablanklines=true log4jdbc.suppress.generated.keys.exception=false
4.0.2 測試
```java
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Properties;
import org.junit.Test;
public class SimpleTest {
@Test
public void test1() {
String sql = "select * " + "from t_user where id=?";
Connection conn = null;
PreparedStatement ps = null;
try {
conn = getConnection();
ps = conn.prepareStatement(sql);
ps.setInt(1, 2);
ps.executeQuery();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
public Connection getConnection() throws IOException, SQLException,
ClassNotFoundException {
String driverClassName = null;
String jdbcUrl = null;
String user = null;
String password = null;
// 讀取類路徑下的配置檔案
InputStream in = getClass().getClassLoader().getResourceAsStream(
"dbconfig.properties");
Properties properties = new Properties();
properties.load(in);
driverClassName = properties.getProperty("driverClassName");
jdbcUrl = properties.getProperty("url");
user = properties.getProperty("username");
password = properties.getProperty("password");
Class.forName(driverClassName);
// 連接配接資訊
Properties info = new Properties();
info.put("user", user);
info.put("password", password);
// 擷取連接配接
Connection connection = DriverManager.getConnection(jdbcUrl, user,
password);
return connection;
}
}
```
4.1 DataSource–c3p0
截至目前為止,官網 對于log4jdbc和資料源的使用還沒有一個很好地例子,以下是官網的截圖:

本人嘗試了一下C3P0資料源,不到之處請指正。
4.1.0 jar包
maven 依賴
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.googlecode.log4jdbc</groupId>
<artifactId>log4jdbc</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.35</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.0</version>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
</dependencies>
4.1.1 配置檔案
此處隻需要 log4j.properties 和log4jdbc.properties 兩個配置檔案即可,配置同4.0中的配置檔案。
4.1.2 測試
package software_test.log4jdbc;
import java.sql.Connection;
import java.sql.PreparedStatement;
import org.junit.Test;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class DataSourceTest {
@Test
public void testC3P0() {
try {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser("root");
dataSource.setPassword("1234");
dataSource.setDriverClass("net.sf.log4jdbc.DriverSpy");
dataSource.setJdbcUrl("jdbc:log4jdbc:mysql://localhost:3306/mvn");
dataSource.setMaxPoolSize();
Connection conn = dataSource.getConnection();
String sql = "select * " + "from t_user where id=?";
PreparedStatement ps = null;
ps = conn.prepareStatement(sql);
ps.setInt(, );
ps.executeQuery();
ps.close();
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
5 聲明
在此将log4jdbc的使用結合官網的幫助文檔中主要的一部分羅列出來。部分不太常用或了解不到位的沒有翻譯,怕誤人子弟,有翻譯不周的地方或了解不到位的地方歡迎指正。
實戰部分,以後會抽時間加入其它的使用方式。
轉載請保留出處。