让JDBC查询日志变得简单

来源:互联网 发布:linux改文件名命令 编辑:程序博客网 时间:2024/05/18 09:14
<script type="text/javascript"><!--google_ad_client = "pub-2947489232296736";/* 728x15, 创建于 08-4-23MSDN */google_ad_slot = "3624277373";google_ad_width = 728;google_ad_height = 15;//--></script><script type="text/javascript"src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
<script type="text/javascript"><!--google_ad_client = "pub-2947489232296736";/* 160x600, 创建于 08-4-23MSDN */google_ad_slot = "4367022601";google_ad_width = 160;google_ad_height = 600;//--></script><script type="text/javascript"src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>

   JDBCjava.sql.PreparedStatement接口的简单扩展可以使查询日志更少犯错,同时整理您的代码。在本文中,IBM电子商务顾问JensWyke向您介绍如何应用基本的封装技术(“通过封装来实现扩展”也称为Decorator模式)来获得最满意的结果。

  在大多数情况下,JDBCPreparedStatements使执行查询更简便并可以显着提升您整体应用程序的性能。当谈到日志查询语句时PreparedStatement接口就显得有些不足了。PreparedStatement的优势在于其可变性,但是一个好的日志条目必须正确描述如何将SQL发送到数据库,它将密切关注用实际的参数值来替换所有参数占位符。虽然有多种方法可以解决这一难题,但没有任何一种易于大规模实施并且大部分将扰乱您的程序代码。

  在本文中,您将了解到如何扩展JDBCPreparedStatement接口来进行查询日志。LoggableStatement类实现PreparedStatement接口,但添加用于获得查询字符串的方法,使用一种适用于记录的格式。使用LoggableStatement类可以减少日志代码中发生错误的几率,生成简单且易于管理的代码。

  注意:本文假设您有丰富的JDBC和PreparedStatement类经验。

  典型日志解决方案  

  表1介绍了数据库查询时通常是如何使用PreparedStatement(虽然忽略了初始化和错误处理)。在本文中,我们将使用SQLquerySELECT做为例子,但讨论使用其它类型的SQL语句,如DELETE、UPDATE和INSERT。

  表1:一个典型的SQL数据库查询


Stringsql="selectfoo,barfromfoobarwherefoo<?andbar=?";StringfooValue=newLong(99);StringbarValue="christmas";Connectionconn=dataSource.getConnection();PreparedStatementpstmt=conn.prepareStatement(sql);pstmt.setLong(1,fooValue);pstmt.setString(2,barValue);ResultSetrs=pstmt.executeQuery();//parseresult...


  表1中一个好的查询日志条目看起来应与下面有几分类似:


Executingquery:selectfoo,barfromfoobarwherefoo<99andbar='christmas'


  下面是查询的日志代码的一个例子。注意:表1中的问号已经被每个参数的值替换。


System.out.println("Executingquery:  selectfoo,barfromfoobarwherefoo<"+fooValue+"andbar='+barValue+"'")


  一种更好的方法是创建方法,我们称之为replaceFirstQuestionMark,它读取查询字符串并用参数值替换问号,如表2所示。这类方法的使用无需创建复制的字符串来描述SQL语句。

  表2:使用replaceFirstQuestionMark来进行字符串替换


//listing1goesheresql=replaceFirstQuestionMark(sql,fooValue);sql=replaceFirstQuestionMark(sql,barValue);System.out.println("Executingquery:"+sql);


  虽然这些解决方案都易于实施,但没有一种是完美的。问题是在更改SQL模板的同时也必须更改日志代码。您将在某一点上犯错几乎是不可避免的。查询将更改但您忘记了更新日志代码,您将结束与将发送到数据库的查询不匹配的日志条目--调试恶梦。

  我们真正需要的是一种使我们能够一次性使用每个参数变量(在我们的实例中为fooValue和barValue)的设计方案。我们希望有一种方法,它使我们能够获得查询字符串,并用实际的参数值替换参数占位符。由于java.sql.PreparedStatement没有此类方法,我们必须自己实现。

  定制解决方案

  我们的PreparedStatement定制实施将做为围绕JDBC驱动器提供的“真实语句(realstatement)”的封装器(Wrapper)。封装器语句将转发所有方法调用(例如setLong(int,long)和setString(int,String))到“真实语句”。在这样做之前它将保存相关的参数值,从而它们可以用于生成日志输出结果。1<script type="text/javascript"><!--google_ad_client = "pub-2947489232296736";/* 728x15, 创建于 08-4-23MSDN */google_ad_slot = "3624277373";google_ad_width = 728;google_ad_height = 15;//--></script><script type="text/javascript"src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
<script type="text/javascript"><!--google_ad_client = "pub-2947489232296736";/* 160x600, 创建于 08-4-23MSDN */google_ad_slot = "4367022601";google_ad_width = 160;google_ad_height = 600;//--></script><script type="text/javascript"src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
原创粉丝点击