如何有效地记录 Java SQL 日志(转)

在常规项目的开发中可能最容易出问题的地方就在于对数据库的处理了,在大部分的环境下,我们对数据库的操作都是使用流行的框架,比如 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

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

效果:

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

 

http://www.cnblogs.com/oneapm/p/4828243.html

时间: 2024-09-23 17:09:12

如何有效地记录 Java SQL 日志(转)的相关文章

如何在MySql中记录SQL日志

SQL server有一个sql profiler可以实时跟踪服务器执行的SQL语句,这在很多时候调试错误非常有用.例如:别人写的复杂代码.生产系统.无调试环境.无原代码... ...   查了一下资料,My SQL可以用下面方法跟踪sql 语句,以下方法以Windows平台为例,linux雷同:   1  配置my.ini文件(在安装目录,linux下文件名为my.cnf)     查找到[mysqld]区段,增加日志的配置,如下示例: [mysqld] log="C:/temp/mysql.

hibernate 查询40万条记录出现 java.sql.SQLException 数字溢出 异常

问题描述 大家好,我用hibernate 查询40万条记录,结果出现 java.sql.SQLException 数字溢出 异常,怎么回事啊?难道 hibernate 支持不了几十万的数据检索???我的代码: List list = session.createQuery("from 表 ").list(); 解决方案 你有没有设置Lazy Loading呀..如果你设的为立即加载的话,几十万的话数据.溢出很正常呀..解决方案二:大哥 你一起弄这么多数据出来能不溢出么?用LAZY解决方

Java log4j日志记录工具配置说明

    Java log4j日志记录工具配置说明 --- 以下是示例配置信息 --- log4j.rootLogger = debug, stdout, logfile log4j.appender.stdout = org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target = System.err log4j.appender.stdout.layout = org.apache.log4j.SimpleLayout log4j

关于java.sql.SQLRecoverableException: Closed Connection异常的解决方案(转)

在项目中碰到了一个应用异常,从表象来看应用僵死.查看Weblogic状态为Running,内存无溢出,但是出现多次线程堵塞.查看Weblogic日志,发现程序出现多次Time Out. 我们知道,Weblogic会自动检测线程运行超时,当超过特点时间(默认600S),即认为此线程为堵塞线程.在日志中发现多次堵塞线程,通过查找资料,发现Weblogic在发生多次线程堵塞后,会自动把应用挂起.默认次数为15次.   是什么造成了线程堵塞呢?通过进一步分析日志,我们发现在线程堵塞之前,发生了多次jav

MS SQL 日志记录管理

    MS SQL的日志信息/日志记录,可能对你来说,既熟悉又陌生,熟悉是因为你可能一直都在使用,查看.关注一些日志信息/记录,例如,作业历史记录:陌生是因 为你可能从不关注日志信息/记录的管理,这里我一直用日志信息/记录这个词,而没有用日志文件这个词来阐述,是想让大家把它和事务日志文件(ldf)区分 开来,网上你用日志文件做搜索关键词,可能搜出来的都是事务日志相关的信息.其实它真的也叫日志文件,这篇文章我大概从日志记录分类.如何查看日志记录. 日志记录的位置.日志记录的设置.为什么错误日志会

hibernate proxool java.sql.SQLException

问题描述 大家好,我现在在项目中使用了hibernate来连接数据库,使用到的连接池是proxool,但奇怪的是,在tomcat的日志中,每隔一定时间就会出现以下信息:09:02:35,768 DEBUG fm_oracleproxool:431 - 009441 (00/09/00) - #7920 removed because it has problems: java.sql.SQLException: ORA-00923: 未找到要求的 FROM 关键字09:02:36,407 DEB

请问为什么我的mybatis 关联查询只有一条记录,但是日志打印出来的Total: 3, 谢谢

问题描述 请问为什么我的mybatis 关联查询只有一条记录,但是日志打印出来的Total: 3, 谢谢 SELECT * FROM JiKeUser; 这个里面有如下三条记录, id userName password ------ --------- ---------- 2 jike00100 666666 3 jike00200 888888 8 author001 123456 SELECT * FROM author; 这个里面也是三条记录, id realName userID I

java.sql.SQLException: Io 异常: 连接超时

问题描述 帮我看看咋回事啊?我搞不懂.就是运行很久的一个项目,最近突然就动不动就登陆不了,然后连首页都显示不出来了.然后只能重启服务,就又没问题了.老师需要重启.帮我看看日志全是这个,是什么意思啊?ERROR 2013-12-06 13:12:20,831 org.logicalcobwebs.proxool.GAP-Pool #0041 encountered errors during destruction: java.sql.SQLException: Io 异常: 连接超时at ora

java.sql.SQLException: Access denied for user &amp;amp;#x27;root&amp;amp;#x27;@&amp;amp;#x27;localhost&amp;amp;#x27; (using password

问题描述 连接MySql数据库,出现java.sql.SQLException:Accessdeniedforuser'root'@'localhost'(usingpassword:YES)的问题,用户名是root,密码是123456,这是我自己设置的密码,为什么连接失败呢???我在MySql中的可视化软件中,测试连接,连接成功,可是为什么在Javaweb中连接数据库不成功呢????比较急!!求解!! 解决方案 本帖最后由 PsMuJIngHua 于 2013-02-02 07:51:44 编