** * 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); }
}
|
|
评论人: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] |
|
|