Java日志框架——查看“完整的执行的SQL语句”
来源:互联网 发布:怕出头知乎 编辑:程序博客网 时间:2024/06/05 16:50
假如我们采用"SLF4J+Logback"的日志框架解决方案,那么该如何配置Logback,使得能够记录“完整的执行的SQL语句”呢?
(假定通过"logback.xml"文件进行Logback配置)
1)除非数据库管理模块自身(比如"mysql:mysql-connector-java")包含有记录“完整的执行的SQL语句”的日志操作语句,否则,我们再怎么配置Logback也无济于事。
2)数据库管理模块有可能不是使用SLF4J作为日志框架,此时需要"jcl-over-slf4j","log4j-over-slf4j","jul-to-slf4j"等日志框架桥接器。可以通过数据库管理模块的pom.xml中声明的日志框架依赖,来确定数据库管理模块所使用的日志框架。不过有个特殊情况,当数据库管理模块使用"Java Logging API"时,无需在pom.xml中声明依赖。因此,我们在搭建实验环境的时候总是添加"jul-to-slf4j"这个日志框架桥接器,并且修改"JDK_HOME/jre/lib/logging.properties"文件中的handlers参数值为"org.slf4j.bridge.SLF4JBridgeHandler"
3)在搭建实验环境,配置"logback.xml"文件的时候,为了排除“由于数据库管理模块的日志记录请求的Level值小于相应Logger实例的Level值,不能达到记录‘完整的执行的SQL语句’的目标”的干扰因素,配置<root>标签中的level值为"all"。
实验环境中的"logback.xml"文件内容如下:
<!--配置debug=true,从而打印任何内部状态下的信息--><configuration debug="true"> <!--配置ConsoleAppender实例--> <appender name="console" class="ch.qos.logback.core.ConsoleAppender"> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <pattern>%-5level %logger %C %M %d{MM/dd-HH:mm:ss.SSS} [%thread] - %msg%n</pattern> </encoder> </appender> <!--可以通过<logger>标签,改变指定的Logger实例的Level值和绑定的Appender--> <!--在Logger实例层次结构中,该Logger实例处于最顶层,其下的子孙Logger实例会继承它的Level值和绑定的Appender,除非特别指定--> <root level="all"> <appender-ref ref="console"/> </root></configuration>
接下来分别介绍4种场景下的Logback配置方案。
一、直接使用"mysql:mysql-connector-java"在本场景中,查询SQL语句的时候,直接使用"mysql:mysql-connector-java"。查看"mysql:mysql-connector-java"的pom.xml文件,可以发现没有声明对任何日志框架的依赖,但还是有可能使用"Java Logging API"这个日志框架。
接下来搭建一个实验环境进行实验。
1、pom.xml
<dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.30</version> </dependency> <!--针对数据库管理模块使用Java Logging API日志框架的情况,配置"org.slf4j:jul-to-slf4j"桥接器--> <!--并且修改JDK_HOME/jre/lib/logging.properties文件中的handlers参数值为org.slf4j.bridge.SLF4JBridgeHandler--> <dependency> <groupId>org.slf4j</groupId> <artifactId>jul-to-slf4j</artifactId> <version>1.7.12</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.12</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.0.13</version> </dependency></dependencies>
2、logback.xml
见“三点注意”中的logback.xml配置。
import java.sql.Connection;import java.sql.DriverManager;import java.sql.PreparedStatement;public class Simple { public static void main(String[] args) throws Exception { Class.forName("com.mysql.jdbc.Driver"); String mysqlUrl = "jdbc:mysql://127.0.0.1:3306/dslztx?useUnicode=true&characterEncoding=gbk&user=dsl&password=dsl"; String sql = "update activity set origin='china' where id=?"; Connection connection = DriverManager.getConnection(mysqlUrl); PreparedStatement statement = connection.prepareStatement(sql); statement.setInt(1, 1); statement.executeUpdate(); }}
4、运行结果
如图1,通过实验可以得出结论:在本场景中,无论如何配置"logback.xml",都不能达到记录“完整的执行的SQL语句”的目标。图1
二、使用"com.googlecode.log4jdbc:log4jdbc"[1]
在本场景中,查询SQL语句的时候,使用"com.googlecode.log4jdbc:log4jdbc","com.googlecode.log4jdbc:log4jdbc"是一个中间层,底层还是使用"mysql:mysql-connector-java"。查看"com.googlecode.log4jdbc:log4jdbc"的pom.xml,可以发现依赖"org.slf4j:slf4j-api",即它使用SLF4J作为日志框架。
接下来搭建一个实验环境进行实验。
1、pom.xml
<dependencies> <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.30</version> </dependency> <!--针对数据库管理模块使用Java Logging API日志框架的情况,配置"org.slf4j:jul-to-slf4j"桥接器--> <!--并且修改JDK_HOME/jre/lib/logging.properties文件中的handlers参数值为org.slf4j.bridge.SLF4JBridgeHandler--> <dependency> <groupId>org.slf4j</groupId> <artifactId>jul-to-slf4j</artifactId> <version>1.7.12</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.12</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.0.13</version> </dependency></dependencies>
2、logback.xml
见“三点注意”中的logback.xml配置。
import java.sql.Connection;import java.sql.DriverManager;import java.sql.PreparedStatement;public class Log4JDBC { public static void main(String[] args) throws Exception { Class.forName("net.sf.log4jdbc.DriverSpy"); String mysqlUrl = "jdbc:log4jdbc:mysql://127.0.0.1:3306/dslztx?useUnicode=true&characterEncoding=gbk&user=dsl&password=dsl"; String sql = "update activity set origin='china' where id=?"; Connection connection = DriverManager.getConnection(mysqlUrl); PreparedStatement statement = connection.prepareStatement(sql); statement.setInt(1, 1); statement.executeUpdate(); }}
4、运行结果
如图2,通过实验可以得出结论:在本场景下,能够达到记录“完整的执行的SQL语句”的目标。
图2
修改后"logback.xml"内容如下:
<!--配置debug=true,从而打印任何内部状态下的信息--><configuration debug="true"> <!--配置ConsoleAppender实例--> <appender name="console" class="ch.qos.logback.core.ConsoleAppender"> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <pattern>%-5level %logger %C %M %d{MM/dd-HH:mm:ss.SSS} [%thread] - %msg%n</pattern> </encoder> </appender> <!--可以通过<logger>标签,改变指定的Logger实例的Level值和绑定的Appender--> <logger name="jdbc.sqlonly" level="debug" additivitt="true"/> <logger name="jdbc.sqltiming" level="debug" additivitt="true"/> <!--在Logger实例层次结构中,该Logger实例处于最顶层,其下的子孙Logger实例会继承它的Level值和绑定的Appender,除非特别指定--> <root level="info"> <appender-ref ref="console"/> </root></configuration>
三、使用"org.springframework:spring-jdbc"
在本场景中,查询SQL语句的时候,使用"org.springframework:spring-jdbc","org.springframework:spring-jdbc"是一个中间层,底层还是使用"mysql:mysql-connector-java"。查看"org.springframework:spring-jdbc"的pom.xml,可以发现它递归依赖"commons-logging:commons-logging",即它使用JCL作为日志框架,因而我们需要"jcl-over-slf4j"这个日志框架桥接器,并且需要在包含"org.springframework:spring-jdbc"依赖的时候,通过<exclusion>标签排除掉"commons-logging:commons-logging"依赖。
本场景中还需要有"com.mchange:c3p0"依赖,查看它的pom.xml,可以发现没有对日志框架的依赖,但是它很有可能选用"Java Logging API"作为日志框架。
接下来搭建一个实验环境进行实验。
1、pom.xml
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>3.2.3.RELEASE</version> <exclusions> <exclusion> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>com.mchange</groupId> <artifactId>c3p0</artifactId> <version>0.9.2</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.30</version> </dependency> <!--针对数据库管理模块使用Java Logging API日志框架的情况,配置"org.slf4j:jul-to-slf4j"桥接器--> <!--并且修改JDK_HOME/jre/lib/logging.properties文件中的handlers参数值为org.slf4j.bridge.SLF4JBridgeHandler--> <dependency> <groupId>org.slf4j</groupId> <artifactId>jul-to-slf4j</artifactId> <version>1.7.12</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>1.7.12</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.12</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.0.13</version> </dependency></dependencies>
2、logback.xml
见“三点注意”中的logback.xml配置。
3、Java代码
import com.mchange.v2.c3p0.ComboPooledDataSource;import org.springframework.jdbc.core.JdbcTemplate;public class SpringJdbcTemplate { public static void main(String[] args) throws Exception { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setDriverClass("com.mysql.jdbc.Driver"); dataSource.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/dslztx?useUnicode=true&characterEncoding=gbk"); dataSource.setUser("dsl"); dataSource.setPassword("dsl"); JdbcTemplate template = new JdbcTemplate(dataSource); String sql = "update activity set origin='china' where id=?"; template.update(sql, 1); }}
4、运行结果
如图3,通过实验得出结论:能够达到记录“完整的执行的SQL语句”的目标。
图3
修改后“logback.xml”内容如下:
<!--配置debug=true,从而打印任何内部状态下的信息--><configuration debug="true"> <!--配置ConsoleAppender实例--> <appender name="console" class="ch.qos.logback.core.ConsoleAppender"> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <pattern>%-5level %logger %C %M %d{MM/dd-HH:mm:ss.SSS} [%thread] - %msg%n</pattern> </encoder> </appender> <!--可以通过<logger>标签,改变指定的Logger实例的Level值和绑定的Appender--> <logger name="org.springframework.jdbc.core.StatementCreatorUtils" level="trace" additivity="true"/> <!--在Logger实例层次结构中,该Logger实例处于最顶层,其下的子孙Logger实例会继承它的Level值和绑定的Appender,除非特别指定--> <root level="info"> <appender-ref ref="console"/> </root></configuration>
四、使用Mybatis
在本场景中,查询SQL语句的时候,使用“org.mybatis:mybatis","org.mybatis:mybatis"是一个中间层,底层还是使用"mysql:mysql-connector-java"。根据文章《Java日志框架——Mybatis选用的日志框架解决方案》,"org.mybatis:mybatis"动态确定选用的第三方日志框架,再结合"org.mybatis:mybatis"的pom.xml文件中的对日志框架依赖的"optional"属性值,可以知道,我们只要在项目中加入对SLF4J的依赖,就可以令mybatis使用SLF4J日志框架。接下来搭建一个实验环境进行实验。
1、pom.xml
<dependencies> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.2.7</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.30</version> </dependency> <!--针对数据库管理模块使用Java Logging API日志框架的情况,配置"org.slf4j:jul-to-slf4j"桥接器--> <!--并且修改JDK_HOME/jre/lib/logging.properties文件中的handlers参数值为org.slf4j.bridge.SLF4JBridgeHandler--> <dependency> <groupId>org.slf4j</groupId> <artifactId>jul-to-slf4j</artifactId> <version>1.7.12</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.12</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.0.13</version> </dependency></dependencies>
2、logback.xml
见“三点注意”中的logback.xml配置。3、Java代码
import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import org.apache.ibatis.session.SqlSessionFactoryBuilder;import java.io.BufferedReader;import java.io.InputStreamReader;import java.util.HashMap;import java.util.Map;public class MybatisLog { public static void main(String[] args) throws Exception { BufferedReader reader = new BufferedReader(new InputStreamReader(MybatisLog.class.getResourceAsStream("/mybatis-config.xml"))); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, "mybatisDB"); reader.close(); SqlSession sqlSession = factory.openSession(); Map<String, Integer> map = new HashMap<String, Integer>(); map.put("id", 1); sqlSession.update("Activity.updateActivity", map); }}
4、运行结果
如图4,通过实验得到结论:能够达到记录“完整的执行的SQL语句”的目标。
图4
修改后"logback.xml"内容如下:
<!--配置debug=true,从而打印任何内部状态下的信息--><configuration debug="true"> <!--配置ConsoleAppender实例--> <appender name="console" class="ch.qos.logback.core.ConsoleAppender"> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <pattern>%-5level %logger %C %M %d{MM/dd-HH:mm:ss.SSS} [%thread] - %msg%n</pattern> </encoder> </appender> <!--可以通过<logger>标签,改变指定的Logger实例的Level值和绑定的Appender--> <logger name="Activity.updateActivity" level="debug" additivity="true"/> <!--在Logger实例层次结构中,该Logger实例处于最顶层,其下的子孙Logger实例会继承它的Level值和绑定的Appender,除非特别指定--> <root level="info"> <appender-ref ref="console"/> </root></configuration>
参考文献:
[1]http://code.google.com/p/log4jdbc/- Java日志框架——查看“完整的执行的SQL语句”
- 怎么为ibatis配置日志,查看执行的sql语句
- mysql开启日志查看执行的sql语句
- 通过日志查看mysql正在执行的SQL语句
- 通过日志查看MySQL正在执行的SQL语句
- SQL Select语句完整的执行顺序:
- SQL Select语句完整的执行顺序
- SQL Select语句完整的执行顺序:
- SQL Select语句完整的执行顺序
- SQL Select语句完整的执行顺序
- SQL语句完整的执行顺序
- SQL Select语句完整的执行顺序
- SQL Select语句完整的执行顺序
- SQL SELECT语句完整的执行顺序
- SQL Select语句完整的执行顺序
- SQL语句完整的执行顺序
- SQL Select语句完整的执行顺序:
- SQL Select语句完整的执行顺序
- POJ 3253 Fence Repair
- 2、装饰者模式
- matlab数据类型转换遇到问题,及解决办法,sym,double ,vpa转换
- SAP系统资产盘盈盘亏的处理
- django-rest-framework指南(1):序列化
- Java日志框架——查看“完整的执行的SQL语句”
- Google编码规范
- hdu 1868 Consecutive sum Java 水题系列
- ReentrantLock解析
- 瓦片地图-Cocos2dx
- OpenGL ES颜色混合
- ScriptManager和UpdatePanel控件的使用
- 【细说PHP学习】第十三章 PHP的错误和异常处理
- HPU 1700:做不出来踢协会!!!