`

运用动态代理来检测未close的JDBC Connection

阅读更多
  虽然spring和Hibernate已经大行其道了。但仍有不少遗留系统,遗留架构仍然是直接采用JDBC编程方式使用数据库的。通常这些架构都会给新人或一些普通技术人员去维护。新人的经验不足,try catch finally三段式编程也就特别容易导致数据库连接未释放。

  这类系统通常使用的过程不会导致问题,一旦突发性大访问量,会出现数据库连接池被耗尽的问题,特别是这类系统通常都是一个大系统的某个子系统,“平时不生病,生病要你命”,客户一抱怨就抱怨你整个系统。这类遗留系统的代码通常都不规范,非常难于调试。
 
  所以能有一个快捷跟踪数据库连未被释放的方法仍然是过度时期的上佳选择。

这类代码通常都有一个典型的DBUtils类,用来维护数据库连接。正好可以用来做手术。
先做一个InvocationHandler:
public class ConnectionInvocationHandler implements InvocationHandler {
        
		private static final long serialVersionUID = 321052036610111535L;

		public final static Timer timer = new Timer("connection-non-close-detector",true);

		private java.sql.Connection innnerConnection;//实际的连接池里的连接   
        
		private TimerTask task;   
           
        public ConnectionInvocationHandler (Connection conn){
        	final Exception ex=new Exception();
            task=new TimerTask(){   
  
                public void run() {//跟踪没有释放的connection调用 
                	 ex.printStackTrace();
                }   
                   
            };   
            timer.schedule(task, 5000);//设置其5秒后运行,根据你环境实际情况设置,假如你觉得5秒不够,那就10秒,也就是说10秒还不释放此连接则超时。   
            this.innnerConnection=conn;   
        }
        /**
         *  Connection的方法拦截
         */
		public Object invoke(Object proxy, Method method, Object[] args)
				throws Throwable {
			if(method.getName().equals("close")){//关闭close跟踪。
				task.cancel();
			}
			Class[] classes=method.getParameterTypes();
			return Connection.class.getMethod(method.getName(), classes).invoke(this.innnerConnection, args);//当调用动态代理的方法的时候,真正的connnection的同名方法被调用		}   
  
}


你的DBUtils类,凡是获得Connection的方法都使用如下代码进行包装:
Connection conn=....
.....
			//the non-closed connect detect code;
			ConnectionInvocationHandler handler=new ConnectionInvocationHandler (conn);
			//use dynamic proxy
			return (Connection) Proxy.newProxyInstance(Connection.class.getClassLoader(), new Class[]{Connection.class}, handler);


然后没有释放的JDBC连接就无所遁形了。

使用动态代理比直接用Proxy设计模式做个代理类多个好处:兼容不同的JDBC版本。否则,不同JDBC版本的系统要使用不同的代理类,一个字“累”。
1
0
分享到:
评论
2 楼 llade 2008-12-29  
ilovepotato 写道

有个小问题请教一下,用Proxy模式也都是对Connection这个接口做代理,为什么会“不同JDBC版本的系统要使用不同的代理类”呢?谢谢

用Proxy模式你必须实现一个Connection接口,这个实现类里面有一个Field引用一个Connection对象,JDBC2.0和3.0的Connection接口是不一样的。所以你在JDBC2.0环境下的实现类拿到3.0环境下会报错。
1 楼 ilovepotato 2008-12-29  
有个小问题请教一下,用Proxy模式也都是对Connection这个接口做代理,为什么会“不同JDBC版本的系统要使用不同的代理类”呢?谢谢

相关推荐

    jdbc连接数据库getConnection 增、删、改、查

    String url = "jdbc:mysql://127.0.0.1:3306/jdbc?useUnicode=true&characterEncoding=utf-8"; String user = "root"; String password = "root"; String driver="com.mysql.jdbc.Driver"; try { Class.forName...

    JDBC详解HTML-JDBC.pp

    1、JDBC(Java Database Connection):java连接数据库统一接口API,底层主要通过直接的JDBC驱动和 JDBC-ODBC桥驱动实现与数据库的连接。 1>.JDBC驱动程序类型: <1>.JDBC-ODBC桥加ODBC驱动程序:需要ODBC驱动,适合...

    greenplum.jar 官方驱动 JDBC

    Connection db = DriverManager.getConnection("jdbc:pivotal:greenplum://192.168.139.128:5432;DatabaseName=postgres", "gpadmin", "gpadmin"); Statement st = db.createStatement(); ResultSet rs = st....

    JDBC事务处理机制探秘

    在JDBC中,打开一个连接对象Connection时,缺省是auto-commit模式,每个SQL语句都被当作一个事务,即每次执行一个语句,都会自动的得到事务确认。为了能将多个SQL语句组合成一个事务,要将auto-commit模式屏蔽掉。在...

    greenplum.jar 官方JDBC驱动

    Connection db = DriverManager .getConnection( "jdbc:pivotal:greenplum://xxx:5432;DatabaseName=core_db", "gpadmin", "gpadmin"); Statement st = db.createStatement(); ResultSet rs = st .executeQuery(...

    jdbc连接db2

    用JDBC连接DB2的例子: 用JDBC连接DB2的例子: import java.sql.*; import COM.ibm.db2.jdbc.app.*; public class DB2Test { public static void main(String[] args) { String JDBCDriver = ...

    使用JDBC总结操作数据库

    2. 通过驱动获取连接对象Connection con=DriverManager.getConnection(“jdbc:oracle:thin:@10.1.12.138:1521:orcl","scott", "de123");//相当与通过我们的用户名和密码登陆我们的pl/sql 3. 通过连接对象创建命令...

    JDBC访问数据库的步骤

    conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/books?","root","111"); System.out.println("Connection Successful!"); stmt=conn.createStatement(); rs=stmt.executeQuery(...

    Access_JDBC30 无使用次数限制 - 破解

    Connection con = DriverManager.getConnection(url); Statement statement = con.createStatement(); statement.execute("drop table if exists test;"); statement.execute("create table if not exists ...

    自己封装的JDBC工具类源码

    其中,与数据库的连接声明成了成员变量,建立连接后可执行各种操作,每个类中的statement、resultset等操作在方法内均关闭,但数据库连接没有关闭,需要在操作完成后调用其中的 closeConnection方法关闭;...

    jdbc练习的一个工具类

    public static void close(ResultSet rs, Statement stat, Connection con) { try { rs.close(); } catch (Exception e) { // TODO Auto-generated catch block // e.printStackTrace(); } try { ...

    JDBC笔记.docx

    二、JDBC接口 所属包:java.sql Javax.sql 1. 创建数据库连接 a) Dirver(驱动) 数据库连接接口,该接口由数据库驱动来实现。 //jdbc协议名:(子协议)数据库协议名://服务器IP地址:端口号/数据库名 private ...

    jdbc连接代码

    String connectionString = "jdbc:mysql://localhost:3306/blog?user=root&password=root"; // 定义驱动数据库的类 String driver = "org.gjt.mm.mysql.Driver"; // 定义连接数据库对象conn Connection ...

    jdbc操作文档,数据库基本操作文档集合

    connection conn = DriverManager.getconnection(url,user,password); 3.创建对象 //create object Statement ste = conn.createStatement(); 4.执行语句 // 对数据库进行插入,更新,删除等操作时用...

    JDBC.txt是链接mysql数据库的源码,复制粘贴即可,需要mysql.jar包

    Connection conn= DriverManager.getConnection(url,"root","123456"); //创建语句对象 String sql="select *from good"; PreparedStatement ptmt=conn.prepareStatement(sql); ResultSet rs= ptmt....

    JSP通过JDBC访问数据库

    是一个最简单,也是学习jsp必须会的一个入门实验----通过jdbc连接数据库。 采用jsp+access数据库实现,同时使用javabean通过jdbc连接数据库。运行结果将显示从数据库查询出的图书。里面包含了javabean的源代码及解释...

    greenplum-jdbc-5.1.4.jar

    import java.sql.Connection; import java.sql.DriverManager;... con.close();  }  } catch (SQLException e ) {  System. out.println("关闭con对象失败!" );  e.printStackTrace();  }  } }

    jdbc-odbc的基本操作

    String dbUrl = "jdbc:odbc:driver={Microsoft Access Driver (*.mdb)};DBQ="+dbPath; cn = DriverManager.getConnection(dbUrl); pstmt = cn.prepareStatement("select PCity from shouji where ?=PhoneNo"); ...

    DruidJDBCUtils.java

    package druidJDBCUtils; ... import javax.sql.DataSource;...import java.sql.... public static void close(Statement statement, Connection connection) { close(null, statement, connection); } }

Global site tag (gtag.js) - Google Analytics