日期:2014-05-16  浏览次数:20469 次

关于 JDBC 资源回收的讨论 !
<div>我们使用连接池访问数据库,是不是在关闭了connection之后它所属的statement和result都会自动关闭了呢?就是说只需要关闭connection? <br>那么这样的话是不是只要在try{...}catch{...}finnally{conn.close();}这样的框架下工作就肯定是不会存在连接资源占用的情况了呢?<br>经过我在DB2上测试的情况是这样的,不知道是不是不同的jdk或者as环境下会有所不同? 我一直无法完全肯定这一问题,请大家赐教!</div>
<div>本来我只要养成在关闭connection之前把其他对象一一关闭的习惯,就不会存在这个问题了,但是我为了偷懒起见,把简单的查询和更新操作封装到了一个基类的公用函数中,方便随时在代码中调用,代码如下:<br>public static ResultSet sysSelect(Connection conn,String sql)throws SQLException{<br>Statement st = null;<br>st = conn.createStatement();<br>return st.executeQuery(sql);<br>}<br>由于这样的功能随时随地会被使用,这不得不使我考虑这个函数中产生中间对象statement st的生存期问题!*_*</div>
<div>-------------------------------------------------<br>是,最起码数据库端资源是得到了释放<br>不过这也不绝对,因为statement,result对应的是curior,而有些<br>DB的curior是share的,<br>总之,关了connection就可以了</div>
<div>-------------------------------------------------<br>你是说:在有的时候就算是释放了connection也可能有部分的Statement和ResultSet还占用着数据库资源? <br>如果是这样的话,那么在这个时候java和数据库的连接虽然断开了,可由于没有在连接的时候预先释放这些Statement和ResultSret资源(在数据库方应该理解为游标或者其他资源),会影响数据库的性能的吧?这似乎无以从程序上来证实! </div>
<div>-------------------------------------------------<br>&gt; 你是说:在有的时候就算是释放了connection也可能有部分的<br>&gt; tatement和ResultSet还占用着数据库资源?<br>不会,本地的statement和ResultSet会被回收,但数据库端的资源不一定会释放,但你不必担心此事,应为这不是一件坏事,就像你用的数据库连接池,数据库也可以对curior做cache,毕竟频繁创建curior对DB来说是比较expansive的.<br>当然,前提是数据库share_curior参数的设置不是0</div>
<div>-------------------------------------------------<br>本地对象如果不被使用的确可以释放,但tcp连接什么时候释放是个问题,还有tcp连接和connection对应还是和resultset对应,这个似乎是未知的,不过看起来java里似乎是和connection对应的,否则只需要全局维护一个长连接connection对象就可以了,只考虑生成(是否可用)的问题而不用考虑关闭的问题(除非出于性能目的,可以考虑多连接加锁的实现,也无需用户去关闭),ado里面好像可以这么做。如果tcp连接过多,一定会把数据库拖垮的。</div>
<div>至于conn, rs, st之间的依赖关系似乎也不明确,所以我在这个时候是自己写一个resultset接口的实现,然后重载close方法,去一一关闭其依赖对象,甚至你可以在final函数里面关闭,不过后者看起来没什么大用。 </div>
<div>-------------------------------------------------<br>Statement也要Close,本人在使用中发现,若单单调用Connection.Close,实际上Connection并不会立即Close,可能要等到垃圾回收Statement后Connection才会Close, 本人使用的数据库是SQLServer. </div>
<div>-------------------------------------------------<br>我曾试过将Connection对象作为一个static属性放在一个类DBConnection中,然后,建立一个连接后,其它所有要用连接的地方就调用<br>DBConnection.connection,<br>最后再关掉,本以为这是一高招,但结果却是不可行。connection被用一次后,调用DBConnection.connection时就不行了。<br>但我认为思路应该是对的,不知是否还有同志尝试过</div>
<div>至于statement,要关掉并不难,可以在一个要连某个数据库的类中将其可connection一同声明为static,这样在任何地方用完后,就可以很方便的关掉了 </div>
<div>-------------------------------------------------<br>全部都要关闭,关闭connection后statement和result还是可以用的,可以在关闭connection后,再试试遍历result还是可以得到数据的,result不关闭会导致游标超出范围等错误 </div>
<div>-------------------------------------------------<br>请问navyzhu和rtm: 你们是在什么数据库上测试得到的这个结果的? <br>我在DB2和ORACLE8.1.2上测试出来的结果都很明显地提示:SQLException:关闭的连接....(所有的conn,st,rs使用的时候是默认方式) </div>
<div>-------------------------------------------------<br>这么看来odbc/jdbc的设计现在也不太适宜了,为什么有conn, st的存在是因为希望可以复用,减少开销,但增加了程序员的负担,可能不多的几行代码,建立对象和关闭对象占了一半。甚至复用也很难实现,因为很多页面中可能只访问一两次数据库,如果没有自己设计或者底层的连接池,页面切换该消耗的还是要消耗。就算不是这样,按照设计的一般标准,需要把粒度细化,这样结果和上面一样,如果要重用,必须附加上多余的耦合变量,更加不好。<br>反过来有了连接池,也基本上不需要conn,或者st,后者根据使用者的经验,似乎可以表达为得到rs后就可以关闭或者直接重用。conn也是可以重用的(否则也就不能连接池了),不过大概需要在前一个返回的resultset被关闭之后,也就是我说的和tcp连接对应的概念,这个和ado不同。 </div>
<div>-------------------------------------------------<br>Connection一旦关闭,所有由它打开的ResultSet不在可用。这在jdk文档中有说明。否则,没有必要定义javax.sql.RowSet了。 </div>
<div>-------------------------------------------------<br>我用的数据库是SQLServer2000,程序是一个数据月结程序,开始我发现月结有时成功,有时失败,看了后台才发现因为Statement没有Close,所以Connection太多以至于打开几百个Connection,结果处理失败。 </div>
<div>-------------------------------------------------<br>Statement,ResultSet肯定都是关闭了得,但是资源还没有释放阿。如果从性能方面考虑的话,一定的明显的关闭Statemen