java连接池实现.docx
- 文档编号:4222644
- 上传时间:2023-05-06
- 格式:DOCX
- 页数:25
- 大小:18.99KB
java连接池实现.docx
《java连接池实现.docx》由会员分享,可在线阅读,更多相关《java连接池实现.docx(25页珍藏版)》请在冰点文库上搜索。
java连接池实现
虽然现在用APACHECOMMONSDBCP可以非常方便的建立数据库连接池,
但是像这篇文章把数据库连接池的内部原理写的这么透彻,注视这么完整,
真是非常难得,让开发人员可以更深层次的理解数据库连接池,真是非常感
谢这篇文章的作者。
importjava.sql.Connection;
importjava.sql.DatabaseMetaData;
importjava.sql.Driver;
importjava.sql.DriverManager;
importjava.sql.SQLException;
importjava.sql.Statement;
importjava.util.Enumeration;
importjava.util.Vector;
publicclassConnectionPool{
privateStringjdbcDriver="";//数据库驱动
privateStringdbUrl="";//数据URL
privateStringdbUsername="";//数据库用户名
privateStringdbPassword="";//数据库用户密码
privateStringtestTable="";//测试连接是否可用的测试表名,默认没有测试表
privateintinitialConnections=10;//连接池的初始大小
privateintincrementalConnections=5;//连接池自动增加的大小
privateintmaxConnections=50;//连接池最大的大小
privateVectorconnections=null;//存放连接池中数据库连接的向量,初始时为null
//它中存放的对象为PooledConnection型
/**
*构造函数
*
*@paramjdbcDriverStringJDBC驱动类串
*@paramdbUrlString数据库URL
*@paramdbUsernameString连接数据库用户名
*@paramdbPasswordString连接数据库用户的密码
*
*/
publicConnectionPool(StringjdbcDriver,StringdbUrl,StringdbUsername,StringdbPassword){
this.jdbcDriver=jdbcDriver;
this.dbUrl=dbUrl;
this.dbUsername=dbUsername;
this.dbPassword=dbPassword;
}
/**
*返回连接池的初始大小
*
*@return初始连接池中可获得的连接数量
*/
publicintgetInitialConnections(){
returnthis.initialConnections;
}
/**
*设置连接池的初始大小
*
*@param用于设置初始连接池中连接的数量
*/
publicvoidsetInitialConnections(intinitialConnections){
this.initialConnections=initialConnections;
}
/**
*返回连接池自动增加的大小、
*
*@return连接池自动增加的大小
*/
publicintgetIncrementalConnections(){
returnthis.incrementalConnections;
}
/**
*设置连接池自动增加的大小
*@param连接池自动增加的大小
*/
publicvoidsetIncrementalConnections(intincrementalConnections){
this.incrementalConnections=incrementalConnections;
}
/**
*返回连接池中最大的可用连接数量
*@return连接池中最大的可用连接数量
*/
publicintgetMaxConnections(){
returnthis.maxConnections;
}
/**
*设置连接池中最大可用的连接数量
*
*@param设置连接池中最大可用的连接数量值
*/
publicvoidsetMaxConnections(intmaxConnections){
this.maxConnections=maxConnections;
}
/**
*获取测试数据库表的名字
*
*@return测试数据库表的名字
*/
publicStringgetTestTable(){
returnthis.testTable;
}
/**
*设置测试表的名字
*@paramtestTableString测试表的名字
*/
publicvoidsetTestTable(StringtestTable){
this.testTable=testTable;
}
/**
*
*创建一个数据库连接池,连接池中的可用连接的数量采用类成员
*initialConnections中设置的值
*/
publicsynchronizedvoidcreatePool()throwsException{
//确保连接池没有创建
//如果连接池己经创建了,保存连接的向量connections不会为空
if(connections!
=null){
return;//如果己经创建,则返回
}
//实例化JDBCDriver中指定的驱动类实例
Driverdriver=(Driver)(Class.forName(this.jdbcDriver).newInstance());
DriverManager.registerDriver(driver);//注册JDBC驱动程序
//创建保存连接的向量,初始时有0个元素
connections=newVector();
//根据initialConnections中设置的值,创建连接。
createConnections(this.initialConnections);
System.out.println("数据库连接池创建成功!
");
}
/**
*创建由numConnections指定数目的数据库连接,并把这些连接
*放入connections向量中
*
*@paramnumConnections要创建的数据库连接的数目
*/
@SuppressWarnings("unchecked")
privatevoidcreateConnections(intnumConnections)throwsSQLException{
//循环创建指定数目的数据库连接
for(intx=0;x //是否连接池中的数据库连接的数量己经达到最大? 最大值由类成员maxConnections //指出,如果maxConnections为0或负数,表示连接数量没有限制。 //如果连接数己经达到最大,即退出。 if(this.maxConnections>0&&this.connections.size()>=this.maxConnections){ break; } //addanewPooledConnectionobjecttoconnectionsvector //增加一个连接到连接池中(向量connections中) try{ connections.addElement(newPooledConnection(newConnection())); }catch(SQLExceptione){ System.out.println("创建数据库连接失败! "+e.getMessage()); thrownewSQLException(); } System.out.println("数据库连接己创建......"); } } /** *创建一个新的数据库连接并返回它 * *@return返回一个新创建的数据库连接 */ privateConnectionnewConnection()throwsSQLException{ //创建一个数据库连接 Connectionconn=DriverManager.getConnection(dbUrl,dbUsername,dbPassword); //如果这是第一次创建数据库连接,即检查数据库,获得此数据库允许支持的 //最大客户连接数目 //connections.size()==0表示目前没有连接己被创建 if(connections.size()==0){ DatabaseMetaDatametaData=conn.getMetaData(); intdriverMaxConnections=metaData.getMaxConnections(); //数据库返回的driverMaxConnections若为0,表示此数据库没有最大 //连接限制,或数据库的最大连接限制不知道 //driverMaxConnections为返回的一个整数,表示此数据库允许客户连接的数目 //如果连接池中设置的最大连接数量大于数据库允许的连接数目,则置连接池的最大 //连接数目为数据库允许的最大数目 if(driverMaxConnections>0&&this.maxConnections>driverMaxConnections){ this.maxConnections=driverMaxConnections; } } returnconn;//返回创建的新的数据库连接 } /** *通过调用getFreeConnection()函数返回一个可用的数据库连接, *如果当前没有可用的数据库连接,并且更多的数据库连接不能创 *建(如连接池大小的限制),此函数等待一会再尝试获取。 * *@return返回一个可用的数据库连接对象 */ publicsynchronizedConnectiongetConnection()throwsSQLException{ //确保连接池己被创建 if(connections==null){ returnnull;//连接池还没创建,则返回null } Connectionconn=getFreeConnection();//获得一个可用的数据库连接 //如果目前没有可以使用的连接,即所有的连接都在使用中 while(conn==null){ //等一会再试 wait(250); conn=getFreeConnection();//重新再试,直到获得可用的连接,如果 //getFreeConnection()返回的为null //则表明创建一批连接后也不可获得可用连接 } returnconn;//返回获得的可用的连接 } /** *本函数从连接池向量connections中返回一个可用的的数据库连接,如果 *当前没有可用的数据库连接,本函数则根据incrementalConnections设置 *的值创建几个数据库连接,并放入连接池中。 *如果创建后,所有的连接仍都在使用中,则返回null *@return返回一个可用的数据库连接 */ privateConnectiongetFreeConnection()throwsSQLException{ //从连接池中获得一个可用的数据库连接 Connectionconn=findFreeConnection(); if(conn==null){ //如果目前连接池中没有可用的连接 //创建一些连接 createConnections(incrementalConnections); //重新从池中查找是否有可用连接 conn=findFreeConnection(); if(conn==null){ //如果创建连接后仍获得不到可用的连接,则返回null returnnull; } } returnconn; } /** *查找连接池中所有的连接,查找一个可用的数据库连接, *如果没有可用的连接,返回null * *@return返回一个可用的数据库连接 */ privateConnectionfindFreeConnection()throwsSQLException{ Connectionconn=null; PooledConnectionpConn=null; //获得连接池向量中所有的对象 Enumerationenumerate=connections.elements(); //遍历所有的对象,看是否有可用的连接 while(enumerate.hasMoreElements()){ pConn=(PooledConnection)enumerate.nextElement(); if(! pConn.isBusy()){ //如果此对象不忙,则获得它的数据库连接并把它设为忙 conn=pConn.getConnection(); pConn.setBusy(true); //测试此连接是否可用 if(! testConnection(conn)){ //如果此连接不可再用了,则创建一个新的连接, //并替换此不可用的连接对象,如果创建失败,返回null try{ conn=newConnection(); }catch(SQLExceptione){ System.out.println("创建数据库连接失败! "+e.getMessage()); returnnull; } pConn.setConnection(conn); } break;//己经找到一个可用的连接,退出 } } returnconn;//返回找到到的可用连接 } /** *测试一个连接是否可用,如果不可用,关掉它并返回false *否则可用返回true * *@paramconn需要测试的数据库连接 *@return返回true表示此连接可用,false表示不可用 */ privatebooleantestConnection(Connectionconn){ try{ //判断测试表是否存在 if(testTable.equals("")){ //如果测试表为空,试着使用此连接的setAutoCommit()方法 //来判断连接否可用(此方法只在部分数据库可用,如果不可用, //抛出异常)。 注意: 使用测试表的方法更可靠 conn.setAutoCommit(true); }else{//有测试表的时候使用测试表测试 //checkifthisconnectionisvalid Statementstmt=conn.createStatement(); stmt.execute("selectcount(*)from"+testTable); } }catch(SQLExceptione){ //上面抛出异常,此连接己不可用,关闭它,并返回false; closeConnection(conn); returnfalse; } //连接可用,返回true returntrue; } /** *此函数返回一个数据库连接到连接池中,并把此连接置为空闲。 *所有使用连接池获得的数据库连接均应在不使用此连接时返回它。 * *@param需返回到连接池中的连接对象 */ publicvoidreturnConnection(Connectionconn){ //确保连接池存在,如果连接没有创建(不存在),直接返回 if(connections==null){ System.out.println("连接池不存在,无法返回此连接到连接池中! "); return; } PooledConnectionpConn=null; Enumerationenumerate=connections.elements(); //遍历连接池中的所有连接,找到这个要返回的连接对象 while(enumerate.hasMoreElements()){ pConn=(PooledConnection)enumerate.nextElement(); //先找到连接池中的要返回的连接对象 if(conn==pConn.getConnection()){ //找到了,设置此连接为空闲状态 pConn.setBusy(false); break; } } } /** *刷新连接池中所有的连接对象 * */ publicsynchronizedvoidrefreshConnections()throwsSQLException{ //确保连接池己创新存在 if(connections==null){ System.out.println("连接池不存在,无法刷新! "); return; } PooledConnectionpConn=null; Enumerationenumerate=connections.elements(); while(enumerate.hasMoreElements()){ //获得一个连接对象 pConn=(PooledConnection)enumerate.nextElement(); //如果对象忙则等5秒,5秒后直接刷新 if(pConn.isBusy()){ wait(5000);//等5秒 } //关闭此连接,用一个新的连接代替它。 closeConnection(pConn.getConnection()); pConn.setConnection(newConnection()); pConn.setBusy(false); } } /** *关闭连接池中所有的连接,并清空连接池。 */ publicsynchronizedvoidcloseConnectionPool()throwsSQLException{ //确保连接池存在,如果不存在,返回 if(connections==null){ System.out.println("连接池不存在,无法关闭! "); return; } PooledConnectionpConn=null; Enumerationenumerate=connections.elements(); while(enumerate.hasMoreElements()){ pConn=(PooledConnection)enumerate.nextElement(); //如果忙,等5秒 if(pConn.isBusy()){ wait(5000);//等5秒 } //5秒后直接关闭它 closeConnection(pConn.getConnection()); //从连接池向量中删除它 connections.removeElement(pConn); } //置连接池为空 connections=null; } /** *关闭一个数据库连接 * *@param需要关闭的数据库连接 */ privatevoidcloseConnection(Connectionconn){ try{ conn.close(); }catch(SQLExceptione){ System.out.println("关闭数据库连接出错: "+e.getMessage()); } } /** *使程序等待给定的毫秒数 * *@param给定的毫秒数 */ privatevoidwait(intmSeconds){ try{ Thread.sleep(mSeconds); }catch(InterruptedExceptione){ } } /** * *内部使用的用于保存连接池中连接对象的类 *此类中有两个成员,一个是数据库的连接,另一个是指示此连接是否 *正在
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- java 连接 实现