自己写的数据库连接池(二)

原创 2004年08月24日 04:20:00
**
 * Statement的自封装,屏蔽了getResultSet,executeQuery,getGeneratedKeys方法 返回自己的接管类
 * 目的适记录SQl的动作和设置相应连接最后活动时间。
 * @author Liudong
 */




package com.drsl.db;

import java.io.*;
import java.sql.*;
import java.util.*;
import java.util.Date;
import java.lang.reflect.*;
import sun.jdbc.odbc.*;
public class StatementObject implements InvocationHandler{
    
    private Statement stm=null;
    private    Statement stm_proxy=null;
    
    private final static String GETRESULTSET_METHOD_NAME = "getResultSet";
    private final static String EXECUTEQUERY_METHOD_NAME = "executeQuery";
    private final static String GETGENERATEDKEYS_METHOD_NAME = "getGeneratedKeys";
    
    private ResultSetObject rso=null;

    public StatementObject(Statement stm){
        this.stm=stm;
    }
    
    public Statement getStatement(){
        if(stm_proxy==null){
            ClassLoader classloader=stm.getClass().getClassLoader();
            Class[] interfaces = stm.getClass().getInterfaces(); 
            
            if(interfaces==null||interfaces.length==0){ 
                interfaces = new Class[1]; 
                interfaces[0] = Statement.class
            }
            
            try{
                
                stm_proxy= (Statement)Proxy.newProxyInstance(classloader,interfaces,this);
                
            }catch(NullPointerException e){
                log(e,"StatementObject getStatement()--error");
            }
            if(stm_proxy!=null)
                log("StatementObject getStatement()--success");
        }
        return stm_proxy;
    }
    
    public Object invoke(Object proxy, Method m, Object[] args)    throws Throwable 
    {
        Object obj = null;
        log("StatementObject--invoke:Method: /""+m.getName()+"/"");
         
        //判断是否调用了getResultSet or executeQuery or getGeneratedKeys
        //是就截获
        if(GETRESULTSET_METHOD_NAME.equals(m.getName()) 
            || EXECUTEQUERY_METHOD_NAME.equals(m.getName())
                || GETGENERATEDKEYS_METHOD_NAME.equals(m.getName())){
                    
            ResultSet rs=(ResultSet)m.invoke(stm, args);
            
            if(rs!=null && rso==null){
                rso=new ResultSetObject(rs);
                obj=rso.getResultSet();
            }else if(rso!=null)
                obj=rso.getResultSet();
            else    
                log("StatementObject--invoke:Method: /""+m.getName()+"/"--失败");
            
        }else{
            obj = m.invoke(stm, args);    
        }
        
        //设置最后一次访问时间,以便及时清除超时的连接
        setLastAccessTime( new Date().getTime());
        return obj;
    }
    /**
    * 将文本信息写入日志文件
    */

    private void log(String msg) {
        ConnectionManager.log(msg);
    }
    
    /**
    * 将文本信息与异常写入日志文件
    */

    private void log(Throwable e, String msg) {
        ConnectionManager.log(e,msg);
    }
    
    //设置最后一次访问时间
    private void setLastAccessTime(long ltime){
        ConnectionObject.setLastAccessTime(ltime);
    }

}
/////////////////////////////////////////////////////////////////////////////////


/**
 * PreparedStatement 的自封装,屏蔽了executeQuery方法 返回自己的接管类
 * 目的适记录SQl的动作和设置相应连接最后活动时间。
 * @author Liudong
 */


package com.drsl.db;

import java.io.*;
import java.sql.*;
import java.util.*;
import java.util.Date;
import java.lang.reflect.*;

public class PreparedStatementObject implements InvocationHandler{
    
    private PreparedStatement ps=null;
    private    PreparedStatement ps_proxy =null;
    
    private final static String EXECUTEQUERY_METHOD_NAME = "executeQuery";
    private ResultSetObject rso=null;

    
    PreparedStatementObject(PreparedStatement ps){
        this.ps=ps;
    }
    public PreparedStatement getPreparedStatement(){
        if(ps_proxy==null){
            ClassLoader classloader=ps.getClass().getClassLoader();
            Class[] interfaces = ps.getClass().getInterfaces(); 
            
            if(interfaces==null||interfaces.length==0){ 
                interfaces = new Class[1]; 
                interfaces[0] = PreparedStatement.class
            } 
    
            try{

                ps_proxy= (PreparedStatement) Proxy.newProxyInstance(classloader,interfaces,this);
                
            }catch(NullPointerException e){
                log(e,"PreparedStatementObject getPreparedStatement()--error");
            }
            if(ps_proxy!=null)
                log("PreparedStatementObject getPreparedStatement()--success");
        }
        return ps_proxy;
    }

    public Object invoke(Object proxy, Method m, Object[] args)    throws Throwable 
    {
        Object obj = null;
        log("PreparedStatementObject--invoke:Method: /""+m.getName()+"/"");
        
        //是否调用了executeQuery 如果是 则接管
        if(EXECUTEQUERY_METHOD_NAME.equals(m.getName())){
            
            ResultSet rs=(ResultSet)m.invoke(ps, args);
            if(rs!=null && rso==null){
                rso=new ResultSetObject(rs);
                obj=rso.getResultSet();
            }else if(rso!=null)
                obj=rso.getResultSet();
            else
                log("PreparedStatementObject--invoke:Method: /""+m.getName()+"/"--失败");
        }else{
            obj = m.invoke(ps, args);
        }
        
        obj = m.invoke(ps, args);    
        //设置最后一次访问时间,以便及时清除超时的连接
        setLastAccessTime( new Date().getTime());
        return obj;
    }
        /**
    * 将文本信息写入日志文件
    */

    private void log(String msg) {
        ConnectionManager.log(msg);
    }
    
    /**
    * 将文本信息与异常写入日志文件
    */

    private void log(Throwable e, String msg) {
        ConnectionManager.log(e,msg);
    }
    //设置最后一次访问时间
    private void setLastAccessTime(long ltime){
        ConnectionObject.setLastAccessTime(ltime);
    }
}


////////////////////////////////////////////////////////////////////////

/**
 * Statement的自封装,屏蔽了getStatement方法 返回自己的接管类
 * 目的适记录SQl的动作和设置相应连接最后活动时间。
 * @author Liudong
 */



package com.drsl.db;

import java.io.*;
import java.sql.*;
import java.util.*;
import java.util.Date;
import java.lang.reflect.*;

public class ResultSetObject implements InvocationHandler{
    
    private ResultSet rs=null;
    private    ResultSet rs_proxy =null;
    
    private final static String GETSTATEMENT_METHOD_NAME = "getStatement";
    private final static String GETMETADATA_METHOD_NAME = "getMetaData";
    
    private StatementObject stmo=null;
    private ResultSetMetaDataObject rsdmo=null;
    

    public ResultSetObject(ResultSet rs){
        this.rs=rs;
    }
    public ResultSet getResultSet(){
        
        if(rs_proxy==null){
            ClassLoader classloader=rs.getClass().getClassLoader();
            Class[] interfaces = rs.getClass().getInterfaces(); 
            
            if(interfaces==null||interfaces.length==0){ 
                interfaces = new Class[1]; 
                interfaces[0] = ResultSet.class
            }
            
            try{
                
                rs_proxy =(ResultSet)Proxy.newProxyInstance(classloader,interfaces,this);
                
            }catch(NullPointerException e){
                log(e,"ResultSetObject getResultSet()--error");
            }
            if(rs_proxy!=null)
                log("ResultSet getResultSet()--success");
        }
        return rs_proxy;
    }
    public Object invoke(Object proxy, Method m, Object[] args)    throws Throwable 
    {
        Object obj = null;
        
        log("ResultSetObject--invoke:Method: /""+m.getName()+"/"");
        //是否执行getStatement,返回Statement 的接管类
        if(GETSTATEMENT_METHOD_NAME.equals(m.getName())){
            
            Statement stm=(Statement)m.invoke(rs,args);
            if(stm!=null && stmo==null){
                stmo=new StatementObject(stm);
                obj=stmo.getStatement();
            }else if(stmo !=null)
                obj=stmo.getStatement();
            else
                log("ResultSetObject--invoke:Method: /""+m.getName()+"/"--失败");
            
        }else if(GETMETADATA_METHOD_NAME.equals(m.getName())){
            
            ResultSetMetaData rsdm=(ResultSetMetaData)m.invoke(rs, args);
            if(rsdm!=null && rsdmo==null){
                rsdmo=new ResultSetMetaDataObject(rsdm);
                obj = rsdmo.getMetaData();
            }else if(rsdmo!=null)
                obj = rsdmo.getMetaData();
            else
                log("ResultSetObject--invoke:Method: /""+m.getName()+"/"--失败");
            
        }else
            obj=m.invoke(rs,args);
        //设置最后一次访问时间,以便及时清除超时的连接
        setLastAccessTime( new Date().getTime());
        return obj;
    }
    /**
    * 将文本信息写入日志文件
    */

    private void log(String msg) {
        ConnectionManager.log(msg);
    }
    
    /**
    * 将文本信息与异常写入日志文件
    */

    private void log(Throwable e, String msg) {
        ConnectionManager.log(e,msg);
    }
    //设置最后一次访问时间
    private void setLastAccessTime(long ltime){
        ConnectionObject.setLastAccessTime(ltime);
    }
}
////////////////////////////////////////////////////////////////////////////


/**
 * ResultSetMetaData 的自封装,屏蔽了executeQuery方法 返回自己的接管类
 * 目的适记录SQl的动作和设置相应连接最后活动时间。
 * @author Liudong
 */


package com.drsl.db;

import java.io.*;
import java.sql.*;
import java.util.*;
import java.util.Date;
import java.lang.reflect.*;

public class ResultSetMetaDataObject implements InvocationHandler{
    
    private ResultSetMetaData rsmd=null;
    private    ResultSetMetaData rsmd_proxy =null;
    //
    
    public ResultSetMetaDataObject(ResultSetMetaData rsmd){
        this.rsmd=rsmd;
    }
    public ResultSetMetaData getMetaData(){
        if(rsmd_proxy==null){
            ClassLoader classloader=rsmd.getClass().getClassLoader();
            Class[] interfaces = rsmd.getClass().getInterfaces(); 
            
            if(interfaces==null||interfaces.length==0){ 
                interfaces = new Class[1]; 
                interfaces[0] = ResultSetMetaData.class
            } 
    
            try{

                rsmd_proxy= (ResultSetMetaData) Proxy.newProxyInstance(classloader,interfaces,this);
                
            }catch(NullPointerException e){
                log(e,"ResultSetMetaDataObject getPreparedStatement()--error");
            }
            if(rsmd_proxy!=null)
                log("ResultSetMetaDataObject getPreparedStatement()--success");
        }
        return rsmd_proxy;
    }

    public Object invoke(Object proxy, Method m, Object[] args)    throws Throwable 
    {
        Object obj = null;
        
        log("ResultSetMetaDataObject--invoke:Method: /""+m.getName()+"/"");
                
        obj = m.invoke(rsmd, args);    
        
        //设置最后一次访问时间,以便及时清除超时的连接
        
        setLastAccessTime( new Date().getTime());
        
        return obj;
    }
        /**
    * 将文本信息写入日志文件
    */

    private void log(String msg) {
        ConnectionManager.log(msg);
    }
    
    /**
    * 将文本信息与异常写入日志文件
    */

    private void log(Throwable e, String msg) {
        ConnectionManager.log(e,msg);
    }
    //设置最后一次访问时间
    private void setLastAccessTime(long ltime){
        ConnectionObject.setLastAccessTime(ltime);
    }
}
////////////////////////////////////////////////////////////////////////////////

/**
 * CallableStatement 的自封装,屏蔽了executeQuery getGeneratedKeys getMetaData 方法 返回自己的接管类
 * 目的是记录SQl的动作和设置相应连接最后活动时间。
 * @author Liudong
 */

package com.drsl.db;

import java.io.*;
import java.sql.*;
import java.util.*;
import java.util.Date;
import java.lang.reflect.*;


public class CallableStatementObject implements InvocationHandler{
    

    
    private CallableStatement cs=null;
    private    CallableStatement cs_proxy =null;
    
    private final static String EXECUTEQUERY_METHOD_NAME = "executeQuery";
    private final static String GETGENERATEDKEYS_METHOD_NAME = "getGeneratedKeys";
    private final static String GETMETADATA_METHOD_NAME = "getMetaData";
    
    private ResultSetObject rso=null;
    private ResultSetMetaDataObject rsmdo=null;
    
    CallableStatementObject(CallableStatement cs){
        this.cs=cs;
    }
    public CallableStatement getCallableStatement(){
        if(cs_proxy==null){
            ClassLoader classloader=cs.getClass().getClassLoader();
            Class[] interfaces = cs.getClass().getInterfaces(); 
            
            if(interfaces==null||interfaces.length==0){ 
                interfaces = new Class[1]; 
                interfaces[0] = CallableStatement.class
            } 
    
            try{

                cs_proxy= (CallableStatement) Proxy.newProxyInstance(classloader,interfaces,this);
                
            }catch(NullPointerException e){
                log(e,"CallableStatementObject getCallableStatement()--error");
            }
            if(cs_proxy!=null)
                log("CallableStatementObject getCallableStatement()--success");
        }
        return cs_proxy;
    }

    public Object invoke(Object proxy, Method m, Object[] args)    throws Throwable 
    {
        Object obj = null;
        log("CallableStatementObject--invoke:Method: /""+m.getName()+"/"");
        
        //是否调用了executeQuery || getGeneratedKeys 如果是 则接管
        if(EXECUTEQUERY_METHOD_NAME.equals(m.getName()) ||
           GETGENERATEDKEYS_METHOD_NAME.equals(m.getName())){
               
            ResultSet rs=(ResultSet)m.invoke(cs, args);
            if(rs!=null && rso==null){
                rso=new ResultSetObject(rs);
                obj=rso.getResultSet();
            }else if(rso!=null)
                obj=rso.getResultSet();
            else
                log("CallableStatementObject--invoke:Method: /""+m.getName()+"/"--失败");
        }else if(GETMETADATA_METHOD_NAME.equals(m.getName())){
            
            ResultSetMetaData rsmd=(ResultSetMetaData)m.invoke(cs, args);
            
            if(rsmd!=null && rsmdo==null){
                rsmdo=new ResultSetMetaDataObject(rsmd);
                obj=rsmdo.getMetaData();
            }else if(rsmdo!=null)
                obj=rsmdo.getMetaData();
            else
                log("CallableStatementObject--invoke:Method: /""+m.getName()+"/"--失败");
        }else
            obj = m.invoke(cs, args);    
        //设置最后一次访问时间,以便及时清除超时的连接
        setLastAccessTime( new Date().getTime());
        return obj;
    }
        /**
    * 将文本信息写入日志文件
    */

    private void log(String msg) {
        ConnectionManager.log(msg);
    }
    
    /**
    * 将文本信息与异常写入日志文件
    */

    private void log(Throwable e, String msg) {
        ConnectionManager.log(e,msg);
    }
    //设置最后一次访问时间
    private void setLastAccessTime(long ltime){
        ConnectionObject.setLastAccessTime(ltime);
    }

    
}




版权声明   给作者写信
本篇文章对您是否有帮助?  投票:         投票结果:   cool.gif  3     sad.gif  0


  评论人:zhouke    参与分: 228    专家分: 30 发表时间: 2004-6-8 下午12:47
看上去挺好的,最好能提供一个简单的使用实例,还有能不能做成一个多数据库的连接,比如也支持ORCALE,MSSQL等!

  评论人:shegg    参与分: 32    专家分: 100 发表时间: 2004-6-10 下午3:30
其实 还有个文件未贴出来。
db.properties
如下(此文件必须和上述几个类在同一个目录下)

################### db.properties #################################
#dbpool info

#日志文件
logfile=D://Site//Drsl//log.txt

#驱动器(如果有多个以冒号‘:’间隔)
drivers=com.mysql.jdbc.Driver:oracle.jdbc.driver.OracleDriver:net.sourceforge.jtds.jdbc.Driver

#数据库信息块(mysql)
mysql.url=jdbc:mysql://localhost:3306/test

mysql.option=&useUnicode=true&characterEncoding=UTF-8&autoReconnect=false
mysql.user=aaa
mysql.password=bbb
mysql.maxconn=0
mysql.minconn=10
mysql.maxonlinetime=30

#数据库信息块(oracle)
oracle.url=jdbc:oracle:thin:@localhost:1521:ORCL

mysql.option=
mysql.user=aaa
mysql.password=bbb
mysql.maxconn=0
mysql.minconn=10
mysql.maxonlinetime=30

#数据库信息块(ms sql)
oracle.url=jdbc:jtds:sqlserver://127.0.0.1:1433/maste

mysql.option=
mysql.user=aaa
mysql.password=bbb
mysql.maxconn=0
mysql.minconn=10
mysql.maxonlinetime=30

#数据库信息块(....)


#end file

然后修改ConnectionObject.newConnection()为

 private ConnectionObject newConnection() {
        ConnectionObject connobj= null; 
        try {
            log("End One Part/r/n");
            
            log("连接池" + name+"创建一个新的连接对象");
             
            String URL=url+option;             log("URL=" +URL );
             
            Connection conn = DriverManager.getConnection(URL,user,password);            
            connobj=new ConnectionObject(conn,false);
            
            freeConnection(connobj);
            countConn++;
            
        } 
        catch (SQLException e) { 
            log(e, "无法创建下列URL的连接: " + url+" for User= " +user+" Password="+password); 
            return null; 
        } 
        return connobj; 
    } 

同时说明一点,对于PreparedStatement 接口,有的jdbc不支持(如mysql5.0 mysql-jdbc 3.0就会导致异常,程序退出时cpu使用率100%)
因此在使用此连接池时请先阅读相应数据库及其jdbc的使用文档。

  评论人:zhouke    参与分: 228    专家分: 30 发表时间: 2004-6-10 下午5:44
真不错,改天试试,偶用的是MSSQL和ORACLE,所以有上面一问!

  评论人:shegg    参与分: 32    专家分: 100 发表时间: 2004-6-11 上午9:09
失误。。。。
文件db.properties 应如下
如下(此文件必须和上述几个类在同一个目录下)

################### db.properties #################################
#dbpool info

#日志文件
logfile=D://Site//Drsl//log.txt

#驱动器(如果有多个以冒号‘:’间隔)
drivers=com.mysql.jdbc.Driver:oracle.jdbc.driver.OracleDriver:net.sourceforge.jtds.jdbc.Driver

#数据库信息块(mysql)
mysql.url=jdbc:mysql://localhost:3306/test?

mysql.option=&useUnicode=true&characterEncoding=UTF-8&autoReconnect=false
mysql.user=aaa
mysql.password=bbb
mysql.maxconn=0
mysql.minconn=10
mysql.maxonlinetime=30

#数据库信息块(oracle)
oracle.url=jdbc:oracle:thin:@localhost:1521:ORCL

oracle.option=
oracle.user=aaa
oracle.password=bbb
oracle.maxconn=0
oracle.minconn=10
oracle.maxonlinetime=30

#数据库信息块(ms sql)
mssql.url=jdbc:jtds:sqlserver://127.0.0.1:1433/maste

mssql.option=
mssql.user=aaa
mssql.password=bbb
mssql.maxconn=0
mssql.minconn=10
mssql.maxonlinetime=30

#数据库信息块(....)

#end file

  评论人:shegg    参与分: 32    专家分: 100 发表时间: 2004-6-11 下午3:55
更正:
mysql.option=&useUnicode=true&characterEncoding=UTF-8&autoReconnect=false

mysql.option=useUnicode=true&characterEncoding=UTF-8&autoReconnect=false

客人: sinboy 发表时间: 2004-6-11 下午6:13
看着不错,可是就是太长,没有耐心看完。我想对数据库访问接口程序最好的封装只需给客户端提供一个设置DRIVER,URL等参数的方法,另外再给客户端提供一个_ResultSet query(String sql)
,int execute(String sql)的方法就好了,不要客户端关心任何有关建立连接、管理连接的底层操作.这样用起来就最好了

  评论人:shegg    参与分: 32    专家分: 100 发表时间: 2004-6-11 下午10:16
设计该连接池时 主要考虑了以下两点

1。使用时除getConnection()需要用到ConnectionManager 的实例外其他的对象实例(如Connection,ResultSet,PreparedStatement,Statement,etc)都可以直接使用常规的类,主要是因为我接管了这些类的方法。(具体请看我程序里的例子)
2。关于设置Driver,在配置文件里设置。

客人: king 发表时间: 2004-7-8 上午9:06
试了一下,出现如下错误,不止为何?
Source not found for $Proxy1.executeQuery(String) line: not available [local variables unavailable]

自己动手写数据库连接池

本篇会实现一个数据库连接池,目的是让大家对数据库连接池的实现方式有一个深入的认识。 为什么要使用连接池? 使用数据库连接池可以节省系统的许多的开销,频繁的操作数据库是一个很耗费资源的行为,网站的响应...
  • DSDS454651
  • DSDS454651
  • 2016年09月13日 23:45
  • 584

Java常用数据库连接池【整理】

应用程序直接获取数据库连接的缺点 用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长。假设网站一天10万访问量,数据库服务器就需要创建10万次连接,极大的浪...
  • qiuzhi__ke
  • qiuzhi__ke
  • 2015年12月08日 19:43
  • 1991

自己动手实现数据库连接池

数据库连接池 1. 数据库连接池是干什么的 假如我们有个应用程序需要每隔10秒查询一次数据库,我们可以用以下方式 方法1:每次查询的时候都新建一个数据库连接,查询结束关闭数据库连接。 ...
  • Deginch
  • Deginch
  • 2017年04月11日 17:02
  • 823

连接池实现连接Mysql数据库

之前操作数据库都是直接使用命令操作(因为做的都是小东西,并发量不会很大),但是如果做实际应用的东西就必须考虑使用连接池实现对数据库的操作,因为数据库的连接和释放都会耗费很大的资源,连接池的原理就是连接...
  • u014594922
  • u014594922
  • 2016年11月02日 19:03
  • 1042

自己用Java编写的连接池

参考网上各方面的资料,自己编写了一个连接池,不过连接池存在一些问题,希望大神们指点,不多说了,直接在代码上有注释: package com.tyxh.mypool; import java.io....
  • tayanxunhua
  • tayanxunhua
  • 2013年08月21日 15:29
  • 5217

ADO.NET 细说数据库连接池

ADO.NET 细说数据库连接池 题外话 通过前几章的学习,不知道大家对ADO.NET有一定的了解了没有。撇开文章质量不讲,必须肯定的是,我是用心去写每一篇文章的。无论是是在排版上,还...
  • moshansk
  • moshansk
  • 2014年08月06日 09:58
  • 1238

集合框架类、JUNIT单元测试、数据库连接池

讲解知识点: (1)集合框架类 (2)JUNIT单元测试 (3)数据库连接池内容记录:(1)集合框架类任务:向List、Set、Map内放置数据,并输出。CollectionTest.javapack...
  • femalcoder
  • femalcoder
  • 2017年02月18日 10:56
  • 402

数据库连接池的好处

对于一个简单的数据库应用,由于对于数据库的访问不是很频繁。这时可以简单地在需要访问数据库时,就新创建一个连接,用完后就关闭它,这样做也不会带来什么明显的性能上的开销。但是对于一个复杂的数据库应用,情况...
  • yzllz001
  • yzllz001
  • 2017年02月03日 11:30
  • 3774

用java实现JDBC数据库连接池

这次写数据库连接池主要想解决的还是servlet访问数据库获取数据的稳定性问题,于是便研究了一下,下面来讲一讲如何用java来写一个适合自己用的数据库连接池。这个东西大家并不陌生,通过使用数据连接池我...
  • novelly
  • novelly
  • 2013年10月07日 23:01
  • 1264

三种数据库连接池的配置及使用(For JDBC)

三种开源数据源c3p0,DBCP以及Tomcat内置数据源(DBCP)的使用简介,
  • u012802702
  • u012802702
  • 2016年04月15日 09:26
  • 8957
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:自己写的数据库连接池(二)
举报原因:
原因补充:

(最多只允许输入30个字)