文档章节

如何有效地记录 Java SQL 日志?

OneAPM蓝海讯通
 OneAPM蓝海讯通
发布于 2015/09/22 10:34
字数 1434
阅读 148
收藏 13

在常规项目的开发中可能最容易出问题的地方就在于对数据库的处理了,在大部分的环境下,我们对数据库的操作都是使用流行的框架,比如 Hibernate 、 MyBatis 等。由于各种原因,我们有时会想知道在这些框架下实际执行的 SQL 究竟是什么。

虽然 Hibernate 可以在配置文件中打开 SHOW SQL 的功能, MyBatis 则可以在 Log4j 的配置文件中配置 SQL 语句的输出,但这些输出是类似这样的 INSERT … ? ? ? 语句,并不是一个完整可以运行的 SQL ,要想知道完整的 SQL 需要手动把参数补齐,如果要调试这样的 SQL 无疑非常痛苦。

Log4jdbc 是一个开源 SQL 日志框架,它使用代理模式实现对常用的 JDBC Driver( Oracle , Derby , MySQL , PostgreSQL , H2 , HSQLDB , …)操作的拦截,记录真实 SQL ,可以将占位符与参数全部合并在一起显示,方便直接拷贝 SQL 在 MySQL 等客户端直接执行,加快调试速度。本文主要介绍如何使用 Log4jdbc 这个可以直接显示完整 SQL 的日志框架,希望对大家能有所帮助。

Log4jdbc 的特点:

Log4jdbc 的官方主页是 https://github.com/arthurblake/log4jdbc ,它具有以下特点:

  • 完全支持 JDBC3 和 JDBC4

  • 配置简单,在大多数情况下,只需要将 JDBC 驱动类改成 net.sf.log4jdbc.DriverSpy ,同时将 jdbc:log4jdbc 添加到现有的 JDBC URL 之前,最后配置日志记录的种类即可

  • 将 Prepared Statements 中的绑定参数自动插入到对应的位置。在大多数情况下极大改善了可读性及调试工作

  • SQL 的耗时信息能被获取从而帮助判断哪些语句执行得过慢,同时这些信息可以被工具识别得到一个关于慢 SQL 的报表

  • SQL 连接信息也可以获取从而帮助诊断关于连接池或线程的问题

  • 兼容任何 JDBC 驱动,需要 JDK1.4 及以上与 Slf4j1.x

  • 开源软件,使用 Apache 2.0 License

###使用 Log4jdbc 的步骤:

感兴趣的朋友可以去 Log4jdbc 的项目主页看它的使用方法,如果单纯使用 Log4jdbc ,不会对 ResultSet 以表格方式呈现,在这里我们使用扩展自 Log4jdbc 的日志框架 Log4jdbc-log4j2 ,它增加了对 ResultSet 以表格方式呈现的处理,项目主页是: https://code.google.com/p/log4jdbc-log4j2/ 。它的使用步骤如下:

1、决定使用哪个版本的 JAR 包:

如果使用 JDK1.5 , 应该使用 JDBC3 版本的 JAR 包即 log4jdbc-log4j2-jdbc3.jar 。

如果使用 JDK1.6 , 应该使用 JDBC4 版本的 JAR 包即 log4jdbc-log4j2-jdbc4.jar (即使实际使用的 JDBC 驱动是 JDBC3 的甚至更老)。

如果使用 JDK1.7 , 应该使用 JDBC4.1 版本的 JAR 包即 log4jdbc-log4j2-jdbc4.1.jar (即使实际使用的 JDBC 驱动是 JDBC3 的甚至更老)。

2、将 JAR 包添加进项目:

将 JAR 包添加进项目有两种方式,第一种是直接将 Log4jdbc-log4j2 和 Slf4j 的 JAR 包添加进 CLASSPATH 中,第二种是使用 MAVEN 方式引入 JAR 包,这里我们主要说明第二种方式。在 pom.xml 文件中,根据使用的 JDBC 驱动的版本来替换 log4jdbc-log4j2-jdbcXX (比如 log4jdbc-log4j2-jdbc4.1 , 或者 log4jdbc-log4j2-jdbc4 , 或者 log4jdbc-log4j2-jdbc3 )。该框架需要配合 Slf4j 一起使用,MAVEN 配置如下:

<dependency>
	<groupId>org.bgee.log4jdbc-log4j2</groupId>
	<artifactId>log4jdbc-log4j2-jdbcXX</artifactId>
	<version>1.16</version>
</dependency>
<dependency>
	<groupId>org.slf4j</groupId>
	<artifactId>jcl-over-slf4j</artifactId>
	<version>1.7.2</version>
</dependency>
<dependency>
	<groupId>org.slf4j</groupId>
	<artifactId>slf4j-api</artifactId>
	<version>1.7.2</version>
</dependency>
<dependency>
	<groupId>org.slf4j</groupId>
	<artifactId>slf4j-log4j12</artifactId>
	<version>1.7.2</version>
</dependency>

3、将项目的配置文件中的 JDBC 驱动类改成 net.sf.log4jdbc.sql.jdbcapi.DriverSpy 。

4、将 jdbc:log4 添加到现有的 JDBC URL 之前:

例如原来的 JDBC URL 是

 jdbc:mysql://localhost:3306/MyDatabase 

,则应该改成:

 jdbc:log4jdbc:mysql://localhost:3306/MyDatabase 

5、配置日志记录的种类:

Log4jdbc 用以下几个可以配置的日志种类:

  • jdbc.sqlonly : 仅记录 SQL

  • jdbc.sqltiming :记录 SQL 以及耗时信息

  • jdbc.audit :记录除了 ResultSet 之外的所有 JDBC 调用信息,会产生大量的记录,有利于调试跟踪具体的 JDBC 问题

  • jdbc.resultset :会产生更多的记录信息,因为记录了 ResultSet 的信息

  • jdbc.connection :记录连接打开、关闭等信息,有利于调试数据库连接相关问题

以上日志种类都可以设置为 DEBUG , INFO 或 ERROR 级别。当设置为 FATAL 或 OFF 时,意味关闭记录。

以下是一个采用 Log4j 作为具体日志系统的典型配置,将这些配置到 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

6、添加 log4jdbc.log4j2.properties 文件:

这是最后一步,在项目的 CLASSPATH 路径下创建一个 log4jdbc.log4j2.properties 文件,告诉 Log4jdbc-log4j2 使用的是 Slf4j 来记录和打印日志,在该配置文件里增加:

log4jdbc.spylogdelegator.name=net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator

最后,运行一下项目,看看效果。

###效果:

如何有效地记录 Java SQL 日志?

上图可以看出,两个 SELECT 语句的执行时间分别是 117 和 552 毫秒,这对于开发调试还是很有帮助的。现在很多项目的压测时和上线后,基本都在使用 OneAPM ,它的数据库监控分析功能更强大一些,不仅可以记录 SQL 日志,还可以定位到操作 SQL 的 Java 代码行,直接在网页上就可以看到效果,使用体验还是不错的。

© 著作权归作者所有

OneAPM蓝海讯通
粉丝 94
博文 631
码字总数 1266889
作品 0
海淀
私信 提问
加载中

评论(1)

栈木头
jdk8肿么破
hibernate xml配置文件参数详解

Hibernate 参数设置一览表 表 3.4. Hibernate JDBC和连接(connection)属性 表 3.5. Hibernate缓存属性 表 3.6. Hibernate事务属性 表 3.7. 其他属性 你应当总是为你的数据库将hibernate.dia...

laigous
2013/01/17
219
0
【Hibernate系列】Hibernate 参数设置一览表

属性名 用途 表 3.4. Hibernate JDBC和连接(connection)属性 表 3.5. Hibernate缓存属性 表 3.6. Hibernate事务属性 表 3.7. 其他属性 你应当总是为你的数据库将hibernate.dialect属性设置成...

磊神Ray
2012/02/15
767
0
log4jdbc数据库访问日志框架使用

log4jdbc官网地址 http://code.google.com/p/log4jdbc/ https://github.com/arthurblake/log4jdbc 当前最新版本是1.2, 支持JDBC3, JDBC4 log4jdbc是在jdbc层的一个日志框架,可以将占位符与参...

cloud-coder
2015/05/27
3.2K
13
数据库中间件 Sharding-JDBC 源码分析 —— 分布式事务(一)之最大努力型

摘要: 原创出处 http://www.iocoder.cn/Sharding-JDBC/transaction-bed/ 「芋道源码」欢迎转载,保留摘要,谢谢! 本文主要基于 Sharding-JDBC 1.5.0 正式版 1. 概述 2. 最大努力送达型 3. 柔...

芋道源码
2017/11/05
1K
1
Hibernate 参数设置一览表

属性名 用途 hibernate.dialect 一个Hibernate Dialect类名允许Hibernate针对特定的关系数据库生成优化的SQL. 取值 full.classname.of.Dialect hibernate.show_sql 输出所有SQL语句到控制台....

lovedreamland
2014/03/29
265
3

没有更多内容

加载失败,请刷新页面

加载更多

一起来学Java8(三)——方法引用

在一起来学Java8(一)——函数式编程中有一个简单的函数式编程的例子: import java.util.function.Consumer;class Person { public static void sayHello(String name) { S...

猿敲月下码
20分钟前
11
0
读书笔记:深入理解ES6(十一)

第十一章 Promise与异步编程   Promise可以实现其他语言中类似Future和Deferred一样的功能,是另一种异步编程的选择,它既可以像事件和回调函数一样指定稍后执行的代码,也可以明确指示代码...

张森ZS
43分钟前
19
0
面试官,Java8 JVM内存结构变了,永久代到元空间

在文章《JVM之内存结构详解》中我们描述了Java7以前的JVM内存结构,但在Java8和以后版本中JVM的内存结构慢慢发生了变化。作为面试官如果你还不知道,那么面试过程中是不是有些露怯?作为面试...

程序新视界
51分钟前
28
0
Elasticsearch 实战(一) - 简介

官腔 Elasticsearch,分布式,高性能,高可用,可伸缩的搜索和分析系统 基本等于没说,咱们慢慢看 1 概述 百度:我们比如说想找寻任何的信息的时候,就会上百度去搜索一下,比如说找一部自己喜...

JavaEdge
56分钟前
22
0
【jQuery基础学习】11 jQuery性能简单优化

本文转载于:专业的前端网站➦【jQuery基础学习】11 jQuery性能简单优化 关于性能优化 合适的选择器 $("#id")会直接调用底层方法,所以这是最快的。如果这样不能直接找到,也可以用find方法继...

前端老手
今天
18
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部