JDBC技术和数据库连接池专题(转载).doc_第1页
JDBC技术和数据库连接池专题(转载).doc_第2页
JDBC技术和数据库连接池专题(转载).doc_第3页
JDBC技术和数据库连接池专题(转载).doc_第4页
JDBC技术和数据库连接池专题(转载).doc_第5页
已阅读5页,还剩23页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

JDBC基础知识一、采用JDBC访问数据库的基本步骤:A.载入JDBC驱动程序B.定义连接URLC.建立连接D.创建Statement对象E.执行查询或更新F.结果处理G.关闭连接二、载入JDBC驱动程序:1.为了使代码尽可能地灵活,我们要避免对类名的引用进行硬编码(hard-coding),因此我们可以采用从Properties文件中载入驱动程序的方法,也可以使用在服务器中配置数据源(DataSource)的方法来避免在代码中硬编码2.在开发过程中要保证CLASSPATH设定中包括驱动程序JAR文件所在的路径。在WEB服务器上部署时要将JAR文件放在Web应用的WEB-INF/lib目录下。如果多个Web应用使用相同的数据库驱动程序可以将JAR文件放置在服务器使用的公共目录commonlib中三、定义连接URL:载入JDBC驱动程序之后,必须指定数据库服务器位置。指向数据库的URL所使用的协议是:jdbc:子协议,并且载入服务器的主机名、端口、数据库名(或引用)。如:Oracle的连接URL:jdbc:oracle:thin:1:1521:UMV2jdbc:oracle:采用Oracle驱动程序thin:指连接服务器所采用的模式1:服务器的地址1521:服务器的监听端口UMV2:数据库名四、建立连接:1.一个数据库连接(Connection)可以通过其自身的getMetaData()来获取它的自身信息2.默认情况下一个数据库的连接是自动提交模式的(auto-commit),也就是说每当一个SQL语句被执行后其改变结果都会被自动提交,如果auto-commit模式被关闭,那么方法commit()必须被显式调用以提交改变结果,否则的话所有对数据库操作的结果都不会被保存五、创建Statement对象:在同一时间下,每个Statement对象只能打开一个ResultSet对象。所以,假如有两个同样结果的结果集在交叉访问,那么这两个结果集必定为两个不同的Statement对象所创建。如果在打开一个新的结果集的时候存在一个已经打开的结果集,则这个已经存在的结果集会被隐式的关闭六、执行查询或更新:在Statement对象中可以执行如下的操作:A.查询操作:executeQuery(SQL语句)B.维护操作:executeUpdate(SQL语句)C.批处理操作:executeBath()七、结果处理:1.ResultSet中行的第一列索引为1,而非0,访问ResultSet中的数据时要使用列名,而非索引但要注意使用列名作为查询条件是大小写敏感的。2.JDBC1.0中,我们只能在ResultSet中向前移动;在JDBC2.0中,我们可以在ResultSet中向下(next)或向上(previous)移动,同样也可以移到特定的行(relative,absolute)3.默认情况下ResultSet是不可更新的,且只能向前移动。下面的代码显示了如何创建一个可滚动的、对更新敏感的ResultSetStatementstmt=con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);ResultSetrs=stmt.executeQuery(SELECTa,bFROMTABLE2);/rswillbescrollable,willnotshowchangesmadebyothers,/andwillbeupdatable4.ResultSet和ResultSetMetaData没有直接提供方法返回查询所返回的行数。然而,在JDBC2.0中,可以通过调用last()方法将游标定位到ResultSet的最后一行,然后调用getRow()方法获取当前的行号。在JDBC1.0中,确定行数的惟一方式是重复调用ResultSet的next()方法,直到它返回false为至八、关闭连接:在关闭数据库连接时应该以ResultSet、Statement、Connection的顺序进行JDBCPreparedStatement(预备语句)一、PreparedStatement(预备语句)的创建:首先按照标准的格式创建参数化语句,在实际使用之前发送参数到数据库进行编译。用问号表示语句中应该为具体的值所替换的位置。每次使用预备语句时,只需要使用相应的setXxx调用,替换语句中标记出来的参数。然后就可以和常规的语句一样,使用executeQuery或execute/executeUpdate修改表中的数据。例如:Connectionconnection=DriverManager.getConnection(url,username,password);/创建带问号的参数化语句Stringtemplate=UPDATEmusicSETprice=?WHEREid=?;PreparedStatementstatement=connection.prepareStatement(template);floatnewPrices=getNewPrices();intrecordingIDs=getIDs();for(inti=0;irecordingIDs.length;i+)/用setXxx代替?statement.setFloat(1,newPricesi);statement.setInt(2,recordingIDsi);/执行预备语句statement.execute();二、使用PreparedStatement的好处:1.依赖于服务器对预编译查询的支持,以及驱动程序处理原始查询的效率,预备语句在性能上的优势可能有很大的不同。2.安全是预备语句的另外一个特点,我们推荐在通过HTML表单接受用户输入,然后对数据库进行更新时,一定要使用预备语句或存储过程。3.预备语句还能够正确地处理嵌入在字符串中的引号以及处理非字符数据(比如向数据库发送序列化后的对象)JDBCCallableStatement(可调用语句)一、使用CallableStatement(可调用语句)的优缺点:1优点:语法错误可以在编译时找出来,而非在运行期间;数据库存储过程的运行可能比常规的SQL查询快得多;程序员只需知道输入和输出参数,不需了解表的结构。另外,由于数据库语言能够访问数据库本地的一下儿功能(序列,触发器,多重游标),因此用它来编写存储过程可能要比使用Java编程语言要简易一些。2缺点:存储过程的商业逻辑在数据库服务器上运行,而非客户机或Web服务器。而行业的发展趋势是尽可能多地将商业逻辑移出数据库,将它们放在JavaBean组件(或者在大型的系统中,EnterPriseJavaBean组件)中,在Web构架上采用这种方式的主要动机是:数据库访问和网络I/O常常是性能的瓶颈。二、使用CallableStatement在JAVA中调用数据库存储过程:1定义对数据库过程的调用A无参数过程:callprocedure_nameB.仅有输入参数的过程:callprocedure_name(?,?.)C有一个输出参数的过程:?Callprocedure_nameD既有输入参数又有输出参数的过程?=callprocedure_name(?,?.)在过程的4种形式中要注意过程可能返回多个输出参数,并且参数的索引值从输出参数开始。因此前面最后例子中,第一个输入参数的索引值是2而不是1。2.为过程准备CallableStatementStringprocedure=“?=callprocedure_name(?,?)”;CallableStatementstatement=connection.prepareCall(procedure);3.提供输入参数的值在执行存储过程之前,我们需要调用与所要设置的项以及参数的类型相对应的setXxx,替换标记出来的输入参数Statement.setString(2,”name”);4.注册输出参数的类型我们必须使用registerOutParameter注册每个输出参数的JDBC类型Statement.registerOutParameter(n,type);5.执行这个存储过程Statement.execute();6.访问返回的输出参数可以通过调用getXxx访问每个对应的输出参数例如:Connectionconnection=DriverManager.getConnection(url,username,password);Stringprocedure=“?=callmyProc(?,?)”;CallableStatementstatement=connection.prepareCall(procedure);statement.setString(2,);statement.setFloat(3,);statement.registerOutParameter(1,Types.INTEGER);statement.execute();introw=statement.getInt(1);CallableStatement 中定义的所有方法都用于处理 OUT 参数或 INOUT 参数的输出部分:注册 OUT 参数的 JDBC 类型(一般 SQL 类型)、从这些参数中检索结果,或者检查所返回的值是否为 JDBC NULL。1、创建 CallableStatement 对象CallableStatement 对象是用 Connection 方法 prepareCall 创建的。下例创建 CallableStatement 的实例,其中含有对已储存过程 getTestData 调用。该过程有两个变量,但不含结果参数:CallableStatement cstmt = con.prepareCall(call getTestData(?, ?);其中?占位符为IN、OUT还是INOUT参数,取决于已储存过程getTestData。2、IN和OUT参数将IN参数传给 CallableStatement 对象是通过 setXXX 方法完成的。该方法继承自 PreparedStatement。所传入参数的类型决定了所用的setXXX方法(例如,用 setFloat 来传入 float 值等)。如果已储存过程返回 OUT 参数,则在执行 CallableStatement 对象以前必须先注册每个 OUT 参数的 JDBC 类型(这是必需的,因为某些 DBMS 要求 JDBC 类型)。注册 JDBC 类型是用 registerOutParameter 方法来完成的。语句执行完后,CallableStatement 的 getXXX 方法将取回参数值。正确的 getXXX 方法是为各参数所注册的 JDBC 类型所对应的 Java 类型。换言之, registerOutParameter 使用的是 JDBC 类型(因此它与数据库返回的 JDBC 类型匹配),而 getXXX 将之转换为 Java 类型。作为示例,下述代码先注册 OUT 参数,执行由 cstmt 所调用的已储存过程,然后检索在 OUT 参数中返回的值。方法 getByte 从第一个 OUT 参数中取出一个 Java 字节,而 getBigDecimal 从第二个 OUT 参数中取出一个 BigDecimal 对象(小数点后面带三位数):CallableStatement cstmt = con.prepareCall(call getTestData(?, ?);cstmt.registerOutParameter(1, java.sql.Types.TINYINT);cstmt.registerOutParameter(2, java.sql.Types.DECIMAL, 3);cstmt.executeQuery();byte x = cstmt.getByte(1);java.math.BigDecimal n = cstmt.getBigDecimal(2, 3);CallableStatement 与 ResultSet 不同,它不提供用增量方式检索大 OUT 值的特殊机制。3、INOUT参数既支持输入又接受输出的参数(INOUT 参数)除了调用 registerOutParameter 方法外,还要求调用适当的 setXXX 方法(该方法是从 PreparedStatement 继承来的)。setXXX 方法将参数值设置为输入参数,而 registerOutParameter 方法将它的 JDBC 类型注册为输出参数。setXXX 方法提供一个 Java 值,而驱动程序先把这个值转换为 JDBC 值,然后将它送到数据库中。这种 IN 值的 JDBC 类型和提供给 registerOutParameter 方法的 JDBC 类型应该相同。然后,要检索输出值,就要用对应的 getXXX 方法。例如,Java 类型为byte 的参数应该使用方法 setByte 来赋输入值。应该给registerOutParameter 提供类型为 TINYINT 的 JDBC 类型,同时应使用 getByte 来检索输出值。下例假设有一个已储存过程 reviseTotal,其唯一参数是 INOUT 参数。方法setByte 把此参数设为 25,驱动程序将把它作为 JDBC TINYINT 类型送到数据库中。接着,registerOutParameter 将该参数注册为 JDBC TINYINT。执行完该已储存过程后,将返回一个新的 JDBC TINYINT 值。方法 getByte 将把这个新值作为 Java byte 类型检索。CallableStatement cstmt = con.prepareCall(call reviseTotal(?);cstmt.setByte(1, 25);cstmt.registerOutParameter(1, java.sql.Types.TINYINT);cstmt.executeUpdate();byte x = cstmt.getByte(1);4、先检索结果,再检索 OUT 参数由于某些 DBMS 的限制,为了实现最大的可移植性,建议先检索由执行CallableStatement 对象所产生的结果,然后再用 CallableStatement.getXXX 方法来检索 OUT 参数。如果 CallableStatement 对象返回多个 ResultSet 对象(通过调用 execute 方法),在检索 OUT 参数前应先检索所有的结果。这种情况下,为确保对所有的结果都进行了访问,必须对 Statement 方法 getResultSet、getUpdateCount 和getMoreResults 进行调用,直到不再有结果为止。检索完所有的结果后,就可用 CallableStatement.getXXX 方法来检索 OUT 参数中的值。5、检索作为OUT参数的NULL值返回到 OUT 参数中的值可能会是JDBC NULL。当出现这种情形时,将对 JDBC NULL 值进行转换以使 getXXX 方法所返回的值为 null、0 或 false,这取决于getXXX 方法类型。对于 ResultSet 对象,要知道0或false是否源于JDBCNULL的唯一方法,是用方法wasNull进行检测。如果 getXXX 方法读取的最后一个值是 JDBC NULL,则该方法返回 true,否则返回 flase。JDBCTransation(事务处理)一、Transation(事务处理)的概念:在更新数据库时,默认情况下,更改是永久性写入到数据库。然而这种默认行为可以通过编写程序来关闭。在自动交付关闭的情况下,如果在更新时发生问题,则对数据库的每个更改都能够取消(或者说回退到最初的值)。如果更新成功,那么之后可以将这些更改永久性提交给数据库。这种方式也称为事务管理。我们需要确保,要么所有的操作都发生,要么所有的操作都不发生。这就是事务管理的原则。二、在JAVA中使用Transation(事务管理)保证数据库的完整性:我们使用try-catch-finally块来正确地应对事务管理,首先,记录自动提交的当前状态。然后,在try块中,调用setAutoCommit(false)并执行一系列的查询或更新。如果发生故障,则在catch块中调用rollback;如果事务成功,则在try块的结尾调用commit。不管哪种方式,都在finally块中重置自动提交的状态。例如:Connectionconnection=DriverManager.getConnection(url,username,password);booleanautoCommit=connection.getAutoCommit();Statementstatement;tryconnection.setAutoCommit(false);/关闭数据库的自动提交statement=connection.createStatement();statement.execute();statement.execute(.);mit();/如果所有语句执行成功则提交事务catch(SQLExceptionsqle)connection.rollback();/如果有异常发生则回滚所有的事务finallyif(statement!=null)statement.close();connection.setAutoCommit(autoCommit);/重置自动提交的状态上面的代码中,从DriverManager获取连接的语句在try/catch块之外。这样除非成功获取连接,否则不会调用rollback。如果把获取连接的语句放在try/catch快之内,一旦在连接成功后发生异常,由于rollback的作用会把已经建立的连接断开。但是getConnection方法也会抛出SQLException异常这个异常要么被外围的方法重新抛出,要么在单独的try/catch块内捕获。JDBC的常用API一、Connection接口:1.createStatement():创建数据库连接2.prepareStatement(Stringsql):创建预处理语句3.prepareCall(Stringsql):创建可调用语句4.getAutoCommit():获取自动提交的模式5.setAutoCommit():设置自动提交的模式6.commit():提交所执行的SQL语句7.rollback():回滚所执行的SQL语句8.getMetaData():获取一个DatabaseMetaData对象,该对象包含了有关数据库的基本信息9.close():关闭数据库连接10.isClose():判断数据库连接是否超时或被显示关闭二、Statement接口:1.execute(Stringsql):执行SQL语句,如果返回值是结果集则为true,否则为false2.executeQuery(Stringsql):执行SQL语句,返回值为ResultSet3.executeUpdate(Stringsql):执行SQL语句,返回值为所影响的行数4.addBatch(Stringsql):向当前Statement对象的命令列表中添加新的批处理SQL语句5.clearBatch():清空当前Statement对象的命令列表6.executeBatch():执行当前Statement对象的批处理语句,返回值为每个语句所影响的函数数组7.getConnection():返回创建了该Statement对象的Connection对象8.getQueryTimeout():获取等待处理结果的时间9.setQueryTimeout():设置等待处理结果的时间三、ResultSet接口:1.first()/beforeFirst():将游标移动到ResultSet中第一条记录(的前面)2.last()/afterLast():将游标移动到ResultSet中最后一条记录(的后面)3.absolute(intcolumn):将游标移动到相对于第一行的指定行,负数则为相对于最后一条记录4.relative(introws):将游标移动到相对于当前行的第几行,正为向下,负为向上5.next():将游标下移一行6.previous():将游标上移一行7.insertRow():向当前ResultSet和数据库中被插入行处插入一条记录8.deleteRow():将当前ResultSet中的当前行和数据库中对应的记录删除9.updateRow():用当前ResultSet中已更新的记录更新数据库中对应的记录10.cancelUpdate():取消当前对ResultSet和数据库中所做的操作11.findColumn(StringcolumnName):返回当前ResultSet中与指定列名对应的索引12.getRow():返回ResultSet中的当前行号13.refreshRow():更新当前ResultSet中的所有记录14.getMetaData():返回描述ResultSet的ResultSetMetaData对象15.isAfterLast():是否到了结尾16.isBeforeFirst():是否到了开头17.isFirst():是否第一条记录18.isLast():是否最后一条记录19.wasNull():检查列值是否为NULL值,如果列的类型为基本类型,且数据库中的值为0,那么这项检查就很重要。由于数据库NULL也返回0,所以0值和数据库的NULL不能区分。如果列的类型为对象,可以简单地将返回值与null比较20.close():关闭当前ResultSet四、ResultSetMetaData接口:1.getColumnCount():返回ResultSet中列的数目2.getColumnName():返回列在数据库中的名称3.getColumnType():返回列的SQL类型4.isReadOnly():表示该数据项是否为只读值5.isNullable():表示该列是否可以存储NULL基于JDBC的数据库连接池技术研究与应用Java应用程序访问数据库的基本原理在Java语言中,JDBC(JavaDataBaseConnection)是应用程序与数据库沟通的桥梁,即Java语言通过JDBC技术访问数据库。JDBC是一种“开放”的方案,它为数据库应用开发人员、数据库前台工具开发人员提供了一种标准的应用程序设计接口,使开发人员可以用纯Java语言编写完整的数据库应用程序。JDBC提供两种API,分别是面向开发人员的API和面向底层的JDBC驱动程序API,底层主要通过直接的JDBC驱动和JDBC-ODBC桥驱动实现与数据库的连接。一般来说,Java应用程序访问数据库的过程(如图1所示)是:装载数据库驱动程序;通过JDBC建立数据库连接;访问数据库,执行SQL语句;断开数据库连接。JDBC作为一种数据库访问技术,具有简单易用的优点。但使用这种模式进行Web应用程序开发,存在很多问题:首先,每一次Web请求都要建立一次数据库连接。建立连接是一个费时的活动,每次都得花费0.05s1s的时间,而且系统还要分配内存资源。这个时间对于一次或几次数据库操作,或许感觉不出系统有多大的开销。可是对于现在的Web应用,尤其是大型电子商务网站,同时有几百人甚至几千人在线是很正常的事。在这种情况下,频繁的进行数据库连接操作势必占用很多的系统资源,网站的响应速度必定下降,严重的甚至会造成服务器的崩溃。不是危言耸听,这就是制约某些电子商务网站发展的技术瓶颈问题。其次,对于每一次数据库连接,使用完后都得断开。否则,如果程序出现异常而未能关闭,将会导致数据库系统中的内存泄漏,最终将不得不重启数据库。还有,这种开发不能控制被创建的连接对象数,系统资源会被毫无顾及的分配出去,如连接过多,也可能导致内存泄漏,服务器崩溃。数据库连接池(connectionpool)的工作原理1、基本概念及原理数据库连接池的基本思想就是为数据库连接建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去。我们可以通过设定连接池最大连接数来防止系统无尽的与数据库连接。更为重要的是我们可以通过连接池的管理机制监视数据库的连接的数量、使用情况,为系统开发、测试及性能调整提供依据。2、服务器自带的连接池JDBC的API中没有提供连接池的方法。一些大型的WEB应用服务器如BEA的WebLogic和IBM的WebSphere等提供了连接池的机制,但是必须有其第三方的专用类方法支持连接池的用法。连接池关键问题分析1、并发问题为了使连接管理服务具有最大的通用性,必须考虑多线程环境,即并发问题。这个问题相对比较好解决,因为Java语言自身提供了对并发管理的支持,使用synchronized关键字即可确保线程是同步的。使用方法为直接在类方法前面加上synchronized关键字,如:publicsynchronizedConnectiongetConnection()2、多数据库服务器和多用户对于大型的企业级应用,常常需要同时连接不同的数据库(如连接Oracle和Sybase)。如何连接不同的数据库呢?我们采用的策略是:设计一个符合单例模式的连接池管理类,在连接池管理类的唯一实例被创建时读取一个资源文件,其中资源文件中存放着多个数据库的url地址()、用户名()、密码()等信息。如tx.url=23:5000/tx_it,tx.user=yang,tx.password=yang321。根据资源文件提供的信息,创建多个连接池类的实例,每一个实例都是一个特定数据库的连接池。连接池管理类实例为每个连接池实例取一个名字,通过不同的名字来管理不同的连接池。对于同一个数据库有多个用户使用不同的名称和密码访问的情况,也可以通过资源文件处理,即在资源文件中设置多个具有相同url地址,但具有不同用户名和密码的数据库连接信息。3、事务处理我们知道,事务具有原子性,此时要求对数据库的操作符合“ALL-ALL-NOTHING”原则,即对于一组SQL语句要么全做,要么全不做。在Java语言中,Connection类本身提供了对事务的支持,可以通过设置Connection的AutoCommit属性为false,然后显式的调用commit或rollback方法来实现。但要高效的进行Connection复用,就必须提供相应的事务支持机制。可采用每一个事务独占一个连接来实现,这种方法可以大大降低事务管理的复杂性。4、连接池的分配与释放连接池的分配与释放,对系统的性能有很大的影响。合理的分配与释放,可以提高连接的复用度,从而降低建立新连接的开销,同时还可以加快用户的访问速度。对于连接的管理可使用空闲池。即把已经创建但尚未分配出去的连接按创建时间存放到一个空闲池中。每当用户请求一个连接时,系统首先检查空闲池内有没有空闲连接。如果有就把建立时间最长(通过容器的顺序存放实现)的那个连接分配给他(实际是先做连接是否有效的判断,如果可用就分配给用户,如不可用就把这个连接从空闲池删掉,重新检测空闲池是否还有连接);如果没有则检查当前所开连接池是否达到连接池所允许的最大连接数(maxConn),如果没有达到,就新建一个连接,如果已经达到,就等待一定的时间(timeout)。如果在等待的时间内有连接被释放出来就可以把这个连接分配给等待的用户,如果等待时间超过预定时间timeout,则返回空值(null)。系统对已经分配出去正在使用的连接只做计数,当使用完后再返还给空闲池。对于空闲连接的状态,可开辟专门的线程定时检测,这样会花费一定的系统开销,但可以保证较快的响应速度。也可采取不开辟专门线程,只是在分配前检测的方法。5、连接池的配置与维护连接池中到底应该放置多少连接,才能使系统的性能最佳?系统可采取设置最小连接数(minConn)和最大连接数(maxConn)来控制连接池中的连接。最小连接数是系统启动时连接池所创建的连接数。如果创建过多,则系统启动就慢,但创建后系统的响应速度会很快;如果创建过少,则系统启动的很快,响应起来却慢。可以在开发时,设置较小的最小连接数,开发起来会快,而在系统实际使用时设置较大的,因为这样对访问客户来说速度会快些。最大连接数是连接池中允许连接的最大数目,具体设置多少,要看系统的访问量,可通过反复测试,找到最佳点。如何确保连接池中的最小连接数呢?有动态和静态两种策略。动态即每隔一定时间就对连接池进行检测,如果发现连接数量小于最小连接数,则补充相应数量的新连接,以保证连接池的正常运转。静态是发现空闲连接不够时再去检查。连接池的实现1、连接池模型连接池类是对某一数据库所有连接的“缓冲池”,主要实现以下功能:从连接池获取或创建可用连接;使用完毕之后,把连接返还给连接池;在系统关闭前,断开所有连接并释放连接占用的系统资源;还能够处理无效连接(原来登记为可用的连接,由于某种原因不再可用,如超时,通讯问题),并能够限制连接池中的连接总数不低于某个预定值和不超过某个预定值。连接池管理类是连接池类的外覆类(wrapper),符合单例模式,即系统中只能有一个连接池管理类的实例。其主要用于对多个连接池对象的管理,具有以下功能:装载并注册特定数据库的JDBC驱动程序;根据属性文件给定的信息,创建连接池对象;为方便管理多个连接池对象,为每一个连接池对象取一个名字,实现连接池名字与其实例之间的映射;跟踪客户使用连接情况,以便需要是关闭连接释放资源。连接池管理类的引入主要是为了方便对多个连接池的使用和管理,如系统需要连接不同的数据库,或连接相同的数据库但由于安全性问题,需要不同的用户使用不同的名称和密码。2、连接池实现下面给出连接池类和连接池管理类的主要属性及所要实现的基本接口:publicclassDBConnectionPoolimplementsTimerListenerprivateintcheckedOut;/已被分配出去的连接数privateArrayListfreeConnections=newArrayList();/容器,空闲池,根据创建时间顺序存放已创建尚未分配出去的连接privateintminConn;/连接池里连接的最小数量privateintmaxConn;/连接池里允许存在的最大连接数privateStringname;/为这个连接池取个名字,方便管理privateStringpassword;/连接数据库时需要的密码privateStringurl;/所要创建连接的数据库的地址privateStringuser;/连接数据库时需要的用户名publicTimertimer;/定时器publicDBConnectionPool(Stringname,StringURL,Stringuser,Stringpassword,intmaxConn)publicsynchronizedvoidfreeConnection(Connectioncon)/使用完毕之后把连接返还给空闲池publicsynchronizedConnectiongetConnection(longtimeout)/得到一个连接,timeout是等待时间publicsynchronizedvoidrelease()/断开所有连接,释放占用的系统资源privateConnectionnewConnection()/新建一个数据库连接publicsynchronizedvoidTimerEvent()/定时器事件处理函数publicclassDBConnectionManagerstaticprivateDBConnectionManagerinstance;/连接池管理类的唯一实例staticprivateintclients;/客户数量privateArrayListdrivers=newArrayList();/容器,存放数据库驱动程序privateHashMappools=newHashMap();/以name/value的形式存取连接池对象的名字及连接池对象privatevoidloadDrivers(Propertiesprops)/装载数据库驱动程序privatevoidcreatePools(Propertiesprops)/根据属性文件提供的信息,创建一个或多个连接池privateDBConnectionManager()/私有构造函数,在其中调用初始化函数init()privatevoidinit()/初始化连接池管理类的唯一实例,由私有构造函数调用staticsynchronizedpublicDBConnectionManagergetInstance()/如果唯一的实例instance已经创建,直接返回这个实例;否则,调用私有构造函数,创建连接池管理类的唯一实例publicConnectiongetConnection(Stringname)/从名字为name的连接池对象/中得到一个连接publicConnectiongetConnection(Stringname,longtime)/从名字为name的连接池对象中取得一个连接,time是等待时间publicvoidfreeConnection(Stringname,Connectioncon)/释放一个连接name是一个连接池对象的名publicsynchronizedvoidrelease()/释放所有资源3、连接池使用上面所实现的连接池在程序开发时如何应用到系统中呢?下面以Servlet为例说明连接池的使用。Servlet的生命周期是:在开始建立servlet时,调用其初始化(init)方法。之后每个用户请求都导致一个调用前面建立的实例的service方法的线程。最后,当服务器决定卸载一个servlet时,它首先调用该servlet的destroy方法。根据servlet的特点,我们可以在初始化函数中生成连接池管理类的唯一实例(其中包括创建一个或多个连接池)。如:publicvoidinit()throwsServletException/getInstance()?DBConnectionManager()?init()connMgr=DBConnectionManager.getInstance();然后就可以在service方法中通过连接池名称使用连接池,执行数据库操作。最后在destroy方法中释放占用的系统资源,如:publicvoiddestroy()connMgr.release();super.destroy();4 一种简单JDBC连接池的实现JDBC连接池在标准JDBC对应用的接口中,并没有提供资源的管理方法。所以,缺省的资源管理由应用自己负责。虽然在JDBC规范中,多次提及资源的关闭/回收及其他的合理运用。但最稳妥的方式,还是为应用提供有效的管理手段。所以,JDBC为第三方应用服务器(ApplicationServer)提供了一个由数据库厂家实现的管理标准接口:连接缓冲(connectionpooling)。引入了连接池(ConnectionPool)的概念,也就是以缓冲池的机制管理数据库的资源。JDBC最常用的资源有三类:-Connection:数据库连接。-Statement:会话声明。-ResultSet:结果集游标。分别存在以下的关系:这是一种爷-父-子的关系,对Connection的管理,就是对数据库资源的管理。举个例子:如果想确定某个数据库连接(Connection)是否超时,则需要确定其(所有的)子Statement是否超时,同样,需要确定所有相关的ResultSet是否超时;在关闭Connection前,需要关闭所有相关的Statement和ResultSet。因此,连接池(ConnectionPool)所起到的作用,不仅仅简单地管理Connection,还涉及到Statement和ResultSet。2.3连接池(ConnectionPool)与资源管理ConnectionPool以缓冲池的机制,在一定数量上限范围内,控制管理Connection,Statement和ResultSet。任何数据库的资源是有限的,如果被耗尽,则无法获得更多的数据服务。在大多数情况下,资源的耗尽不是由于应用的正常负载过高,而是程序原因。在实际工作中,数据资源往往是瓶颈资源,不同的应用都会访问同一数据源。其中某个应用耗尽了数据库资源后,意味其他的应用也无法正常运行。因此,ConnectionPool的第一个任务是限制:每个应用或系统可以拥有的最大资源。也就是确定连接池的大小(PoolSize)。ConnectionPool的第二个任务:在连接池的大小(PoolSize)范围内,最大限度地使用资源,缩短数据库访问的使用周期。许多数据库中,连接(Connection)并不是资源的最小单元,控制Statement资源比Connection更重要。以Oracle为例:每申请一个连接(Connection)会在物理网络(如TCP/IP网络)上建立一个用于通讯的连接,在此连接上还可以申请一定数量的Statement。同一连接可提供的活跃Statement数量可以达到几百。在节约网络资源的同时,缩短了每次会话周期(物理连接的建立是个费时的操作)。但在一般的应用中,多数按照2.1范例操作,这样有10个程序调用,则会产生10次物理连接,每个Statement单独占用一个物理连接,这是极大的资源浪费。ConnectionPool可以解决这个问题,让几十、几百个Statement只占用同一个物理连接,发挥数据库原有的优点。通过ConnectionPool对资源的有效管理,应用可以获得的Statement总数到达:(并发物理连接数)x(每个连接可提供的Statement数量)例如某种数据库可同时建立的物理连接数为200个,每个连接可同时提供250个Statement,那么ConnectionPool最终为应用提供的并发Statement总数为:200x250=50,000个。这是个

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论