Java实现数据库连接池的方法
本文实例讲述了Java实现数据库连接池的方法。分享给大家供大家参考。具体如下:
packagecom.kyo.connection; 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{ privateConnectionParamparam; privateStringtestTable=""; //测试连接是否可用的测试表名,默认没有测试表 privateVectorconnections=null; //存放连接池中数据库连接的向量,初始时为 //null,它中存放的对象为PooledConnection型 publicvoidsetParam(ConnectionParamparam){ this.param=param; } publicConnectionParamgetParam(){ returnparam; } /** *构造函数 * *@paramparam */ publicConnectionPool(ConnectionParamparam){ this.param=param; } /** * *获取测试数据库表的名字 * *@return测试数据库表的名字 */ publicStringgetTestTable(){ returnthis.testTable; } /** * *设置测试表的名字 * *@paramtestTable *String测试表的名字 */ publicvoidsetTestTable(StringtestTable){ this.testTable=testTable; } /** *创建一个数据库连接池,连接池中的可用连接的数量采用类成员initialConnections中设置的值 */ publicsynchronizedvoidcreatePool()throwsException{ //确保连接池没有创建 //如果连接池己经创建了,保存连接的向量connections不会为空 if(connections!=null){ return;//如果己经创建,则返回 } //实例化JDBCDriver中指定的驱动类实例 Driverdriver=(Driver)(Class.forName(this.param.getDriver()) .newInstance()); DriverManager.registerDriver(driver);//注册JDBC驱动程序 //创建保存连接的向量,初始时有0个元素 connections=newVector(); //根据initialConnections中设置的值,创建连接。 createConnections(this.param.getMinConnection()); System.out.println("数据库连接池创建成功!"); } /** * *创建由numConnections指定数目的数据库连接,并把这些连接放入connections向量中 * *@paramnumConnections *要创建的数据库连接的数目 */ privatevoidcreateConnections(intnumConnections)throwsSQLException{ //循环创建指定数目的数据库连接 for(intx=0;x<numConnections;x++){ //是否连接池中的数据库连接的数量己经达到最大?最大值由类成员maxConnections,指出,如果maxConnections //为0或负数,表示连接数量没有限制。 //如果连接数己经达到最大,即退出。 if(this.param.getMaxConnection()>0 &&this.connections.size()>=this.param.getMaxConnection()){ 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(this.param.getUrl(), this.param.getUser(),this.param.getPassword()); //如果这是第一次创建数据库连接,即检查数据库,获得此数据库允许支持的 //最大客户连接数目 //connections.size()==0表示目前没有连接己被创建 if(connections.size()==0){ DatabaseMetaDatametaData=conn.getMetaData(); intdriverMaxConnections=metaData.getMaxConnections(); //数据库返回的driverMaxConnections若为0,表示此数据库没有最大 //连接限制,或数据库的最大连接限制不知道 //driverMaxConnections为返回的一个整数,表示此数据库允许客户连接的数目 //如果连接池中设置的最大连接数量大于数据库允许的连接数目,则置连接池的最大 //连接数目为数据库允许的最大数目 if(driverMaxConnections>0 &&this.param.getMaxConnection()>driverMaxConnections){ this.param.setMaxConnection(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(this.param.getIncrementalConnections()); //重新从池中查找是否有可用连接 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){ } } /** * *内部使用的用于保存连接池中连接对象的类此类中有两个成员,一个是数据库的连接,另一个是指示此连接是否正在使用的标志。 */ classPooledConnection{ Connectionconnection=null;//数据库连接 booleanbusy=false;//此连接是否正在使用的标志,默认没有正在使用 //构造函数,根据一个Connection构告一个PooledConnection对象 publicPooledConnection(Connectionconnection){ this.connection=connection; } //返回此对象中的连接 publicConnectiongetConnection(){ returnconnection; } //设置此对象的,连接 publicvoidsetConnection(Connectionconnection){ this.connection=connection; } //获得对象连接是否忙 publicbooleanisBusy(){ returnbusy; } //设置对象的连接正在忙 publicvoidsetBusy(booleanbusy){ this.busy=busy; } } }
希望本文所述对大家的java程序设计有所帮助。