日期:2014-05-16  浏览次数:20529 次

JDBC Debug补丁方案参考
当我们过了一段时间发现程序中总是有些JDBC的异常, 又不找不到错误的地方。
主要原因在于 系统大,不熟悉流程. 没办法知道报错之前的上一个链接是怎么回事..
对于一个成型的系统. 我们应该修改下实现 去调试.. 记录下每个连接的记录 这样报错的时候就知道上一个链接是哪个, 从而找到这个错误的代码

这样的问题难确定在于, 如果你写错了 类似不关闭连接之类的. 程序可以从你的代码处顺利走过. 下一个使用的地方才报错.. 所以错误信息没什么帮助.

遇到一些[高雅]的人更加是吐血一般,“你看报错信息 就是你们的代码报错的!”— 汗

透明化JDBC的一个小例子. 问题解决之后马上还原.. 用于调试这类问题应该好办.

package ro.kifs.diagnostic;

import java.io.PrintStream;
import java.sql.CallableStatement;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.Savepoint;
import java.sql.Statement;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.UUID;

public class Connection
  implements java.sql.Connection
{
  private static HashMap _openedConnections = new HashMap();
  java.sql.Connection _conn;
  private String _connid;
  private static SimpleDateFormat sdf = new SimpleDateFormat("MM/DD HH:mm:ss");

  public static String getGUID()
  {
    String ret = UUID.randomUUID().toString();

    return ret;
  }

  public void registerOpenedConnection()
  {
    _openedConnections.put(getConnectionId(), whoCalledMe());
  }

  public static String getStillOpenedConnsStackTraces() {
    StringBuffer sb = new StringBuffer(5000);
    try
    {
      sb.append("<br>\n Who calls the unclosed connections: <BR>\n");

      Iterator it = _openedConnections.entrySet().iterator();
      Map.Entry me = null;
      while (it.hasNext()) {
        me = (Map.Entry)it.next();
        sb.append("<BR>\n");
        sb.append("" + me.getValue());
      }
    }
    catch (Exception ex)
    {
      sb.append("ex when iterating the connection stacktraces: " + ex.getMessage());
    }

    return sb.toString();
  }

  private void $init$() {
    this._connid = null; }

  public String getConnectionId() {
    return this._connid;
  }

  public String whoCalledMe()
  {
    StringBuffer ret = new StringBuffer(300);
    StackTraceElement[] trace = new Throwable().getStackTrace();

    for (int i = 0; i < trace.length - 1; ++i) {
      ret.append(trace[i].getClassName());
      ret.append(".");
      ret.append(trace[i].getMethodName());
      ret.append("() line:");
      ret.append("() line:");
      ret.append(trace[i].getLineNumber());
      ret.append("<BR>\n");
    }
    ret.append(sdf.format(new Date()));

    return ret.toString(); }

  public Connection(java.sql.Connection wrappedConnection) {
    $init$();
    this._conn = wrappedConnection;
    this._connid = getGUID();
    registerOpenedConnection();
  }

  public Statement createStatement() throws SQLException {
    return this._conn.createStatement();
  }

  public PreparedStatement prepareStatement(String sql) throws SQLException {
    return this._conn.prepareStatement(sql); }

  public CallableStatement prepareCall(String sql) throws SQLException {
    return this._conn.prepareCall(sql); }

  public String nativeSQL(String sql) throws SQLException {
    return this._conn.nativeSQL(sql); }

  public void setAutoCommit(boolean autoCommit) throws SQLException {
    this._conn.setAutoCommit(autoCommit); }

  public boolean getAutoCommit() throws SQLException {
    return this._conn.getAutoCommit(); }

  public void commit() throws SQLException {
    this._conn.commit(); }

  public void rollback() throws SQLException {
    this._conn.rollback();
  }

  public void close() throws SQLException {
    try {
      this._conn.close();
      this._conn = null;
      _openedConnections.remove(getConnectionId());
    }
    catch (Exception x) {
      System.out.println(">>>>>>>>>>EX la wrapper.close(): " + x.getMessage());
      x.printStackTrace();
    }
  }

  public boolean isClosed() throws SQLException {
    return