sun.jdbc报错连数据库查询问题,isClose方法为什么报错

数据检测jdbc connection与数据库断开? - ITeye问答
有一个C/S模式的java系统,使用jdbc与oracle连接。与数据库连接正常,此时若拔掉网线,将网络物理连接断开,系统与数据库的连接肯定已断开,请问使用什么方法可以测试出与数据库连接已断开?
我用过isClose(),conn==null均不行。
你可以模仿连接池校验有效连接,如果是mysql的话,select now() from dual
当然我们程序最简单的实现,就是用异常捕获了,把你的连接放在try里面,连不上或者其他无法预知的异常在catch里面处理。
try catch 抓到异常!再做相应处理!
我刚也试了一下,断开后会在这里抛出异常
conn=DriverManager.getConnection(url, "autek", "flyvideo");
你可以在catch里面做相应处理. 此时isClose(),conn==null这些你都无法获得了,所以是不行的.
执行语句"select 1"
已解决问题
未解决问题温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
拒绝中成长
LOFTER精选
网易考拉推荐
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
CallableStatement cstmt = con.prepareCall("{call getTestData(?, ?)}");
其中?占位符为INOUT还是INOUT参数,取决于已储存过程getTestData2IN和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 值的特殊机制3INOUT参数既支持输入又接受输出的参数(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 方法 getResultSetgetUpdateCount 和getMoreResults 进行调用,直到不再有结果为止检索完所有的结果后,就可用 CallableStatement.getXXX 方法来检索 OUT 参数中的值5检索作为OUT参数的NULL值返回到 OUT 参数中的值可能会是JDBC NULL当出现这种情形时,将对 JDBC NULL 值进行转换以使 getXXX 方法所返回的值为 null0 或 false,这取决于getXXX 方法类型对于 ResultSet 对象,要知道0或false是否源于JDBCNULL的唯一方法,是用方法wasNull进行检测如果 getXXX 方法读取的最后一个值是 JDBC NULL,则该方法返回 true,否则返回 flase
JDBC-Transation(事务处理)一Transation(事务处理)的概念:在更新数据库时,默认情况下,更改是永久性写入到数据库然而这种默认行为可以通过编写程序来关闭在自动交付关闭的情况下,如果在更新时发生问题,则对数据库的每个更改都能够取消(或者说回退到最初的值)如果更新成功,那么之后可以将这些更改永久性提交给数据库这种方式也称为事务管理我们需要确保,要么所有的操作都发生,要么所有的操作都不发生这就是事务管理的原则二在JAVA中使用Transation(事务管理)保证数据库的完整性:我们使用try-catch-finally块来正确地应对事务管理,首先,记录自动提交的当前状态然后,在try块中,调用setAutoCommit(false)并执行一系列的查询或更新如果发生故障,则在catch块中调用rollback;如果事务成功,则在try块的结尾调用commit不管哪种方式,都在finally块中重置自动提交的状态例如:Connection&connection&=&DriverManager.getConnection(url,username,password);boolean&autoCommit&=&connection.getAutoCommit();Statement&try{&&&&connection.setAutoCommit(false);&&&&//&关闭数据库的自动提交&&&&statement&=&connection.createStatement();statement.execute();statement.execute(..);<mit();&&&&&&&&&&&&&&&&//&如果所有语句执行成功则提交事务}catch(SQLException&sqle){&&&&connection.rollback();&&&&&&&&&&&&&&&&//&如果有异常发生则回滚所有的事务}finally{&&&&if(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(String&sql):创建预处理语句&&&&3.prepareCall(String&sql):创建可调用语句&&&&4.getAutoCommit():获取自动提交的模式&&&&5.setAutoCommit():设置自动提交的模式&&&&mit():提交所执行的SQL语句&&&&7.rollback():回滚所执行的SQL语句&&&&8.getMetaData():获取一个DatabaseMetaData对象,该对象包含了有关数据库的基本信息&&&&9.close():关闭数据库连接&&&&10.isClose():判断数据库连接是否超时或被显示关闭二Statement接口:&&&&1.execute(String&sql):执行SQL语句,如果返回值是结果集则为true,否则为false&&&&2.executeQuery(String&sql):执行SQL语句,返回值为ResultSet&&&&3.executeUpdate(String&sql):执行SQL语句,返回值为所影响的行数&&&&4.addBatch(String&sql):向当前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(int&column):将游标移动到相对于第一行的指定行,负数则为相对于最后一条记录&&&&4.relative(int&rows):将游标移动到相对于当前行的第几行,正为向下,负为向上&&&&5.next():将游标下移一行&&&&6.previous():将游标上移一行&&&&7.insertRow():向当前ResultSet和数据库中被插入行处插入一条记录&&&&8.deleteRow():将当前ResultSet中的当前行和数据库中对应的记录删除&&&&9.updateRow():用当前ResultSet中已更新的记录更新数据库中对应的记录&&&&10.cancelUpdate():取消当前对ResultSet和数据库中所做的操作&&&&11.findColumn(String&columnName):返回当前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(Java&DataBase&Connection)是应用程序与数据库沟通的桥梁,&即Java语言通过JDBC技术访问数据库JDBC是一种开放的方案,它为数据库应用开发人员数据库前台工具开发人员提供了一种标准的应用程序设计接口,使开发人员可以用纯Java语言编写完整的数据库应用程序JDBC提供两种API,分别是面向开发人员的API和面向底层的JDBC驱动程序API,底层主要通过直接的JDBC驱动和JDBC-ODBC桥驱动实现与数据库的连接&一般来说,Java应用程序访问数据库的过程(如图1所示)是:&装载数据库驱动程序;&通过JDBC建立数据库连接;&访问数据库,执行SQL语句;&断开数据库连接&JDBC作为一种数据库访问技术,具有简单易用的优点但使用这种模式进行Web应用程序开发,存在很多问题:首先,每一次Web请求都要建立一次数据库连接建立连接是一个费时的活动,每次都得花费0.05s~1s的时间,而且系统还要分配内存资源这个时间对于一次或几次数据库操作,或许感觉不出系统有多大的开销可是对于现在的Web应用,尤其是大型电子商务网站,同时有几百人甚至几千人在线是很正常的事在这种情况下,频繁的进行数据库连接操作势必占用很多的系统资源,网站的响应速度必定下降,严重的甚至会造成服务器的崩溃不是危言耸听,这就是制约某些电子商务网站发展的技术瓶颈问题其次,对于每一次数据库连接,使用完后都得断开否则,如果程序出现异常而未能关闭,将会导致数据库系统中的内存泄漏,最终将不得不重启数据库还有,这种开发不能控制被创建的连接对象数,系统资源会被毫无顾及的分配出去,如连接过多,也可能导致内存泄漏,服务器崩溃&数据库连接池(connection&pool)的工作原理&1基本概念及原理&数据库连接池的基本思想就是为数据库连接建立一个缓冲池预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从缓冲池中取出一个,使用完毕之后再放回去我们可以通过设定连接池最大连接数来防止系统无尽的与数据库连接更为重要的是我们可以通过连接池的管理机制监视数据库的连接的数量使用情况,为系统开发测试及性能调整提供依据&2服务器自带的连接池&JDBC的API中没有提供连接池的方法一些大型的WEB应用服务器如BEA的WebLogic和IBM的WebSphere等提供了连接池的机制,但是必须有其第三方的专用类方法支持连接池的用法&连接池关键问题分析&1并发问题&为了使连接管理服务具有最大的通用性,必须考虑多线程环境,即并发问题这个问题相对比较好解决,因为Java语言自身提供了对并发管理的支持,使用synchronized关键字即可确保线程是同步的使用方法为直接在类方法前面加上synchronized关键字,如:&public&synchronized&Connection&getConnection()&&2多数据库服务器和多用户&对于大型的企业级应用,常常需要同时连接不同的数据库(如连接Oracle和Sybase)如何连接不同的数据库呢?我们采用的策略是:设计一个符合单例模式的连接池管理类,在连接池管理类的唯一实例被创建时读取一个资源文件,其中资源文件中存放着多个数据库的url地址(&poolName.url&)用户名(&poolName.user&)密码(&poolName.password&)等信息如tx.url=172.21.15.123: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连接池实现&下面给出连接池类和连接池管理类的主要属性及所要实现的基本接口:&public&class&DBConnectionPool&implements&TimerListener{&private&int&checkedO//已被分配出去的连接数&private&ArrayList&freeConnections&=&new&ArrayList();//容器,空闲池,根据创建时间顺序存放已创建尚未分配出去的连接&private&int&minC//连接池里连接的最小数量&private&int&maxC//连接池里允许存在的最大连接数&private&String&//为这个连接池取个名字,方便管理&private&String&//连接数据库时需要的密码&private&String&//所要创建连接的数据库的地址&private&String&//连接数据库时需要的用户名&public&Timer&//定时器&public&DBConnectionPool(String&name,&String&URL,&String&user,&Stringpassword,&int&maxConn)&public&synchronized&void&freeConnection(Connection&con)&//使用完毕之后把连接返还给空闲池&public&synchronized&Connection&getConnection(long&timeout)//得到一个连接,timeout是等待时间&public&synchronized&void&release()//断开所有连接,释放占用的系统资源&private&Connection&newConnection()//新建一个数据库连接&public&synchronized&void&TimerEvent()&//定时器事件处理函数&}public&class&DBConnectionManager&{&static&private&DBConnectionManager&//连接池管理类的唯一实例&static&private&int&//客户数量&private&ArrayList&drivers&=&new&ArrayList();//容器,存放数据库驱动程序&private&HashMap&pools&=&new&HashMap&();//以name/value的形式存取连接池对象的名字及连接池对象&private&void&loadDrivers(Properties&props)//装载数据库驱动程序&private&void&createPools(Properties&props)//根据属性文件提供的信息,创建一个或多个连接池&private&DBConnectionManager()//私有构造函数,在其中调用初始化函数init()&private&void&init()//初始化连接池管理类的唯一实例,由私有构造函数调用&static&synchronized&public&DBConnectionManager&getInstance()//如果唯一的实例instance已经创建,直接返回这个实例;否则,调用私有构造函数,创建连接池管理类的唯一实例&public&Connection&getConnection(String&name)//从名字为name的连接池对象//中得到一个连接&public&Connection&getConnection(String&name,&long&time)//从名字为name&的连接池对象中取得一个连接,time是等待时间&public&void&freeConnection(String&name,&Connection&con)//释放一个连接name是一个连接池对象的名&public&synchronized&void&release()//释放所有资源&}&&&3连接池使用&上面所实现的连接池在程序开发时如何应用到系统中呢?下面以Servlet为例说明连接池的使用&Servlet的生命周期是:在开始建立servlet时,调用其初始化(init)方法之后每个用户请求都导致一个调用前面建立的实例的service方法的线程最后,当服务器决定卸载一个servlet时,它首先调用该servlet的&destroy方法&根据servlet的特点,我们可以在初始化函数中生成连接池管理类的唯一实例(其中包括创建一个或多个连接池)如:&public&void&init()&throws&ServletException&{&&&//&getInstance()?DBConnectionManager()?init()connMgr&=&DBConnectionManager.getInstance();&&}&&&然后就可以在service方法中通过连接池名称使用连接池,执行数据库操作最后在destroy方法中释放占用的系统资源,如:&&public&void&destroy()&{&&connMgr.release();&super.destroy();&&}
4 一种简单JDBC连接池的实现
JDBC连接池&在标准JDBC对应用的接口中,并没有提供资源的管理方法所以,缺省的资源管理由应用自己负责虽然在JDBC规范中,多次提及资源的关闭/回收及其他的合理运用但最稳妥的方式,还是为应用提供有效的管理手段所以,JDBC为第三方应用服务器(Application&Server)提供了一个由数据库厂家实现的管理标准接口:连接缓冲(connection&pooling)引入了连接池(&Connection&Pool&)的概念&,也就是以缓冲池的机制管理数据库的资源&JDBC最常用的资源有三类:&-Connection:&数据库连接&-Statement:&会话声明&-ResultSet:&结果集游标&分别存在以下的关系&:&
这是一种&'爷-父-子&的关系,对Connection的管理,就是对数据库资源的管理举个例子:&如果想确定某个数据库连接(Connection)是否超时,则需要确定其(所有的)子Statement是否超时,同样,需要确定所有相关的ResultSet是否超时;在关闭Connection前,需要关闭所有相关的Statement和ResultSet&因此,连接池(Connection&Pool)所起到的作用,不仅仅简单地管理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总数为:&200&x&250&=&50,000个这是个并发数字,很少有系统会突破这个量级所以在本节的开始,指出资源的耗尽与应用程序直接管理有关&对资源的优化管理,很大程度上依靠数据库自身的JDBC&Driver是否具备有些数据库的JDBC&Driver并不支持Connection与Statement之间的逻辑连接功能,如SQLServer,我们只能等待她自身的更新版本了&对资源的申请释放回收共享和同步,这些管理是复杂精密的所以,ConnectionPool另一个功能就是,封装这些操作,为应用提供简单的,甚至是不改变应用风格的调用接口&
3.简单JDBC连接池的实现&根据第二章中原理机制,Snap-ConnectionPool(一种简单快速的连接池工具)按照部分的JDBC规范,实现了连接池所具备的对数据库资源有效管理功能&3.1体系描述&在JDBC规范中,应用通过驱动接口(Driver&Interface)直接方法数据库的资源为了有效合理地管理资源,在应用与JDBC&Driver之间,增加了连接池:&Snap-ConnectionPool并且通过面向对象的机制,使连接池的大部分操作是透明的参见下图,Snap-ConnectionPool的体系:&
图中所示,通过实现JDBC的部分资源对象接口(&Connection,&Statement,&ResultSet&),在&Snap-ConnectionPool内部分别产生三种逻辑资源对象:&PooledConnection,&PooledStatement和&PooledResultSet它们也是连接池主要的管理操作对象,并且继承了JDBC中相应的从属关系这样的体系有以下几个特点:&-透明性在不改变应用原有的使用JDBC驱动接口的前提下,提供资源管理的服务应用系统,如同原有的&JDBC,使用连接池提供的逻辑对象资源简化了应用程序的连接池改造&-资源封装复杂的资源管理被封装在&Snap-ConnectionPool内部,不需要应用系统过多的干涉管理操作的可靠性安全性由连接池保证应用的干涉(如:主动关闭资源),只起到优化系统性能的作用,遗漏操作不会带来负面影响&-资源合理应用按照JDBC中资源的从属关系,Snap-ConnectionPool不仅对Connection进行缓冲处理,对Statement也有相应的机制处理在2.3已描述,合理运用Connection和Statement之间的关系,可以更大限度地使用资源所以,Snap-ConnectionPool封装了Connection资源,通过内部管理PooledConnection,为应用系统提供更多的Statement资源&-资源连锁管理Snap-ConnectionPool包含的三种逻辑对象,继承了JDBC中相应对象之间的从属关系在内部管理中,也依照从属关系进行连锁管理例如:判断一个Connection是否超时,需要根据所包含的Statement是否活跃;判断Statement也要根据ResultSet的活跃程度&
3.2连接池集中管理ConnectionManager&ConnectionPool是Snap-ConnectionPool的连接池对象在Snap-ConnectionPool内部,可以指定多个不同的连接池(ConnectionPool)为应用服务ConnectionManager管理所有的连接池,每个连接池以不同的名称区别通过配置文件适应不同的数据库种类如下图所示:&
通过ConnectionManager,可以同时管理多个不同的连接池,提供通一的管理界面在应用系统中通过ConnectionManager和相关的配置文件,可以将凌乱散落在各自应用程序中的数据库配置信息(包括:数据库名用户密码等信息),集中在一个文件中便于系统的维护工作&3.3连接池使用范例&对2.1的标准JDBC的使用范例,改为使用连接池,结果如下:&import&java.sql.*;import&net.snapbug.util.dbtool.*;..ConnectionPool&dbConn&=&ConnectionManager&&&&&&&&&&&&&&&&&&&.getConnectionPool("testOracle"&);Statement&st&=&dbConn.createStatement();ResultSet&rs&=&st.executeQuery(&&&&&&&&&&&&&&select&*&from&demo_table&);some&data&source&operation&&&&&&in&herers.close();st.close();在例子中,Snap-ConnectionPool封装了应用对Connection的管理只要改变JDBC获取Connection的方法,为获取连接池(ConnectionPool)(粗体部分),其他的数据操作都可以不做修改按照这样的方式,Snap-ConnectionPool可帮助应用有效地管理数据库资源如果应用忽视了最后资源的释放:&rs.close()&和&st.close(),连接池会通过超时(time-out)机制,自动回收&4.小结&无论是Snap-ConnectionPool还是其他的数据库连接池,都应当具备一下基本功能:&-对源数据库资源的保护&-充分利用发挥数据库的有效资源&-简化应用的数据库接口,封闭资源管理&-对应用遗留资源的自动回收和整理,提高资源的再次利用率&在这个前提下,应用程序才能投入更多的精力于各自的业务逻辑中数据库资源也不再成为系统的瓶颈&注:&在网站&可免费下载Snap-ConnectionPool及更详细的文档
附:JDBC连接各种数据库的方法及技巧
一连接各种数据库方式速查表下面罗列了各种数据库使用JDBC连接的方式,可以作为一个手册使用1Oracle8/8i/9i数据库(thin模式)Class.forName(oracle.jdbc.driver.OracleDriver).newInstance();String url=jdbc:oracle:thin:@localhost:1521: //orcl为数据库的SIDString user=String password=Connection conn= DriverManager.getConnection(url,user,password);2DB2数据库Class.forName(com.ibm.db2.jdbc.app.DB2Driver ).newInstance();String url=jdbc:db2://localhost:5000/ //sample为你的数据库名String user=String password=;Connection conn= DriverManager.getConnection(url,user,password);3Sql Server7.0/2000数据库Class.forName(com.microsoft.jdbc.sqlserver.SQLServerDriver).newInstance();String url=jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=//mydb为数据库String user=String password=;Connection conn= DriverManager.getConnection(url,user,password);4Sybase数据库Class.forName(com.sybase.jdbc.SybDriver).newInstance();String url = jdbc:sybase:Tds:localhost:5007/myDB;//myDB为你的数据库名Properties sysProps = System.getProperties();SysProps.put(user,userid);SysProps.put(password,user_password);Connection conn= DriverManager.getConnection(url, SysProps);5Informix数据库Class.rmix.jdbc.IfxDriver).newInstance();String url = jdbc:informix-sqli://123.45.67.89:1533/myDB:INFORMIXSERVER=user=password= //myDB为数据库名Connection conn= DriverManager.getConnection(url);6MySQL数据库Class.forName(org.gjt.mm.mysql.Driver).newInstance();String url =jdbc:mysql://localhost/myDB?user=soft&password=soft1234&useUnicode=true&characterEncoding=8859_1//myDB为数据库名Connection conn= DriverManager.getConnection(url);7PostgreSQL数据库Class.forName(org.postgresql.Driver).newInstance();String url =jdbc:postgresql://localhost/myDB //myDB为数据库名String user=String password=Connection conn= DriverManager.getConnection(url,user,password);8access数据库直连用ODBC的Class.forName(sun.jdbc.odbc.JdbcOdbcDriver) ;String url=jdbc:odbc:Driver={MicroSoft Access Driver (*.mdb)};DBQ=+application.getRealPath(/Data/ReportDemo.mdb);Connection conn = DriverManager.getConnection(url,,);Statement stmtNew=conn.createStatement() ;二JDBC连接MySql方式下面是使用JDBC连接MySql的一个小的教程1查找驱动程序MySQL目前提供的java驱动程序为Connection/J,可以从MySQL官方网站下载,并找到mysql-connector-java-3.0.15-ga-bin.jar文件,此驱动程序为纯java驱动程序,不需做其他配置2动态指定classpath如果需要执行时动态指定classpath,就在执行时采用-cp方式否则将上面的.jar文件加入到classpath环境变量中3加载驱动程序try{Class.forName(com.mysql.jdbc.Driver);System.out.println(Success loading Mysql Driver!);}catch(Exception e){System.out.println(Error loading Mysql Driver!);e.printStackTrace();}4设置连接的urljdbc:mysql://localhost/databasename[?pa=va][&pa=va]三以下列出了在使用JDBC来连接Oracle数据库时可以使用的一些技巧1在客户端软件开发中使用Thin驱动程序在开发Java软件方面,Oracle的数据库提供了四种类型的驱动程序,二种用于应用软件appletsservlets等客户端软件,另外二种用于数据库中的Java存储过程等服务器端软件在客户机端软件的开发中,我们可以选择OCI驱动程序或Thin驱动程序OCI驱动程序利用Java本地化接口(JNI),通过Oracle客户端软件与数据库进行通讯Thin驱动程序是纯Java驱动程序,它直接与数据库进行通讯为了获得最高的性能,Oracle建议在客户端软件的开发中使用OCI驱动程序,这似乎是正确的但我建议使用Thin驱动程序,因为通过多次测试发现,在通常情况下,Thin驱动程序的性能都超过了OCI驱动程序2关闭自动提交功能,提高系统性能在第一次建立与数据库的连接时,在缺省情况下,连接是在自动提交模式下的为了获得更好的性能,可以通过调用带布尔值false参数的Connection类的setAutoCommit()方法关闭自动提交功能,如下所示:conn.setAutoCommit(false);值得注意的是,一旦关闭了自动提交功能,我们就需要通过调用Connection类的commit()和rollback()方法来人工的方式对事务进行管理3在动态SQL或有时间限制的命令中使用Statement对象在执行SQL命令时,我们有二种选择:可以使用PreparedStatement对象,也可以使用Statement对象无论多少次地使用同一个SQL命令,PreparedStatement都只对它解析和编译一次当使用Statement对象时,每次执行一个SQL命令时,都会对它进行解析和编译这可能会使你认为,使用PreparedStatement对象比使用Statement对象的速度更快然而,我进行的测试表明,在客户端软件中,情况并非如此因此,在有时间限制的SQL操作中,除非成批地处理SQL命令,我们应当考虑使用Statement对象此外,使用Statement对象也使得编写动态SQL命令更加简单,因为我们可以将字符串连接在一起,建立一个有效的SQL命令因此,我认为,Statement对象可以使动态SQL命令的创建和执行变得更加简单4利用helper函数对动态SQL命令进行格式化在创建使用Statement对象执行的动态SQL命令时,我们需要处理一些格式化方面的问题例如,如果我们想创建一个将名字O'Reilly插入表中的SQL命令,则必须使用二个相连的''号替换O'Reilly中的'号完成这些工作的最好的方法是创建一个完成替换操作的helper方法,然后在连接字符串心服用公式表达一个SQL命令时,使用创建的helper方法与此类似的是,我们可以让helper方法接受一个Date型的值,然后让它输出基于Oracle的to_date()函数的字符串表达式5利用PreparedStatement对象提高数据库的总体效率在使用PreparedStatement对象执行SQL命令时,命令被数据库进行解析和编译,然后被放到命令缓冲区然后,每当执行同一个PreparedStatement对象时,它就会被再解析一次,但不会被再次编译在缓冲区中可以发现预编译的命令,并且可以重新使用在有大量用户的企业级应用软件中,经常会重复执行相同的SQL命令,使用PreparedStatement对象带来的编译次数的减少能够提高数据库的总体性能如果不是在客户端创建预备执行PreparedStatement任务需要的时间长于Statement任务,我会建议在除动态SQL命令之外的所有情况下使用PreparedStatement对象6在成批处理重复的插入或更新操作中使用PreparedStatement对象如果成批地处理插入和更新操作,就能够显著地减少它们所需要的时间Oracle提供的Statement和 CallableStatement并不真正地支持批处理,只有PreparedStatement对象才真正地支持批处理我们可以使用addBatch()和executeBatch()方法选择标准的JDBC批处理,或者通过利用PreparedStatement对象的setExecuteBatch()方法和标准的executeUpdate()方法选择速度更快的Oracle专有的方法要使用Oracle专有的批处理机制,可以以如下所示的方式调用setExecuteBatch():PreparedStatement pstmt3Dtry {((OraclePreparedStatement)pstmt).setExecuteBatch(30);...pstmt.executeUpdate();}调用setExecuteBatch()时指定的值是一个上限,当达到该值时,就会自动地引发SQL命令执行,标准的executeUpdate()方法就会被作为批处理送到数据库中我们可以通过调用PreparedStatement类的sendBatch()方法随时传输批处理任务7使用Oracle locator方法插入更新大对象(LOB)Oracle的PreparedStatement类不完全支持BLOB和CLOB等大对象的处理,尤其是Thin驱动程序不支持利用PreparedStatement对象的setObject()和setBinaryStream()方法设置BLOB的值,也不支持利用setCharacterStream()方法设置CLOB的值只有locator本身中的方法才能够从数据库中获取LOB类型的值可以使用PreparedStatement对象插入或更新LOB,但需要使用locator才能获取LOB的值由于存在这二个问题,因此,我建议使用locator的方法来插入更新或获取LOB的值8使用SQL92语法调用存储过程在调用存储过程时,我们可以使用SQL92或Oracle PL/SQL,由于使用Oracle PL/SQL并没有什么实际的好处,而且会给以后维护你的应用程序的开发人员带来麻烦,因此,我建议在调用存储过程时使用SQL929使用Object SQL将对象模式转移到数据库中既然可以将Oracle的数据库作为一种面向对象的数据库来使用,就可以考虑将应用程序中的面向对象模式转到数据库中目前的方法是创建Java bean作为伪装的数据库对象,将它们的属性映射到关系表中,然后在这些bean中添加方法尽管这样作在Java中没有什么问题,但由于操作都是在数据库之外进行的,因此其他访问数据库的应用软件无法利用对象模式如果利用Oracle的面向对象的技术,可以通过创建一个新的数据库对象类型在数据库中模仿其数据和操作,然后使用JPublisher等工具生成自己的Java bean类如果使用这种方式,不但Java应用程序可以使用应用软件的对象模式,其他需要共享你的应用中的数据和操作的应用软件也可以使用应用软件中的对象模式10利用SQL完成数据库内的操作我要向大家介绍的最重要的经验是充分利用SQL的面向集合的方法来解决数据库处理需求,而不是使用Java等过程化的编程语言如果编程人员要在一个表中查找许多行,结果中的每个行都会查找其他表中的数据,最后,编程人员创建了独立的UPDATE命令来成批地更新第一个表中的数据与此类似的任务可以通过在set子句中使用多列子查询而在一个UPDATE命令中完成当能够在单一的SQL命令中完成任务,何必要让数据在网上流来流去的?我建议用户认真学习如何最大限度地发挥SQL的功能.引文来源&&----------------------------一键转贴,快速捕捉生活精彩,赢每周好礼!
阅读(3129)|
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
loftPermalink:'',
id:'fks_',
blogTitle:'JDBC技术和数据库连接池专题',
blogAbstract:'JDBC基础知识一采用JDBC访问数据库的基本步骤:&&&&A.载入JDBC驱动程序&&&&B.定义连接URL&&&&C.建立连接&&&&D.创建Statement对象&&&&E.执行查询或更新&&&&F.结果处理&&&&G.关闭连接二载入JDBC驱动程序:1.为了使代码尽可能地灵活,我们要避免对类名的引用进行硬编码(hard-coding),因此我们可以采用从Properties文件中载入驱动程序的方法,也可以使用在服务器中配置数据源(DataSource)的方法来避免在代码中硬编码2.在开发过程中要保证CLASSPATH设定中包括驱动程序JAR文件所在的路径在WEB服务器上部署时要将JAR文件放在Web应用的WEB-INF/lib目录下如果多个Web应用使用相同的数据库驱动程序可以将JAR文件放置在服务器使用的公共目录&%CATALINA_HOME%&\\common\\lib中',
blogTag:'',
blogUrl:'blog/static/',
isPublished:1,
istop:false,
modifyTime:8,
publishTime:5,
permalink:'blog/static/',
commentCount:1,
mainCommentCount:1,
recommendCount:0,
bsrk:-100,
publisherId:0,
recomBlogHome:false,
currentRecomBlog:false,
attachmentsFileIds:[],
groupInfo:{},
friendstatus:'none',
followstatus:'unFollow',
pubSucc:'',
visitorProvince:'',
visitorCity:'',
visitorNewUser:false,
postAddInfo:{},
mset:'000',
remindgoodnightblog:false,
isBlackVisitor:false,
isShowYodaoAd:false,
hostIntro:'拒绝中成长',
hmcon:'0',
selfRecomBlogCount:'0',
lofter_single:''
{list a as x}
{if x.moveFrom=='wap'}
{elseif x.moveFrom=='iphone'}
{elseif x.moveFrom=='android'}
{elseif x.moveFrom=='mobile'}
${a.selfIntro|escape}{if great260}${suplement}{/if}
{list a as x}
推荐过这篇日志的人:
{list a as x}
{if !!b&&b.length>0}
他们还推荐了:
{list b as y}
转载记录:
{list d as x}
{list a as x}
{list a as x}
{list a as x}
{list a as x}
{if x_index>4}{break}{/if}
${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}
{list a as x}
{if !!(blogDetail.preBlogPermalink)}
{if !!(blogDetail.nextBlogPermalink)}
{list a as x}
{if defined('newslist')&&newslist.length>0}
{list newslist as x}
{if x_index>7}{break}{/if}
{list a as x}
{var first_option =}
{list x.voteDetailList as voteToOption}
{if voteToOption==1}
{if first_option==false},{/if}&&“${b[voteToOption_index]}”&&
{if (x.role!="-1") },“我是${c[x.role]}”&&{/if}
&&&&&&&&${fn1(x.voteTime)}
{if x.userName==''}{/if}
网易公司版权所有&&
{list x.l as y}
{if defined('wl')}
{list wl as x}{/list}

我要回帖

更多关于 jdbc批处理uodate报错 的文章

 

随机推荐