- 浏览: 227454 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
redlwb225:
刚好用到,总体可用,但是转int和short的方法有些问题,会 ...
java :获取wav文件的编码格式,音频的通道数,采样频率,采样位数 -
一个人de我们:
[/b][b][i][/i][u][/u]引用
[img][ ...
java通过文件头内容判断文件类型 -
gpinglee:
排版太乱了吧,看起来很吃力。
关于 JDBC 资源回收的讨论 ! -
emeraldttt:
写的非常好 很多东西总结的浅显易懂
01、全面阐释和精彩总结JPA -
咸蛋超人:
请问下,安装后,是如何使用的
常用Eclipse插件
关于 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>> 你是说:在有的时候就算是释放了connection也可能有部分的<br>> 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肯定都是关闭了得,但是资源还没有释放阿。如果从性能方面考虑的话,一定的明显的关闭Statement,ResultSet,还有两点需要注意:<br>1,不要隐式产生Statement,ResultSet对象<br>2,关闭对象一定要在finally中关闭 </div>
<div>-------------------------------------------------------------------------------------<br>JDBC3.0规范中提出了一个新的规范:把Statement也进行缓存(一般是应用服务器厂商实现),这样就可以在不同的connection之间可以共享Statement。所以我个人以为,在释放connection之前,最好先close Statement,这样有利于statement的重用(而且这也是规范所推荐的比较好的编程习惯)。 </div>
<div>-------------------------------------------------------------------------------------<br>Statement和PreparedStatement已经将数据库操作封装的很好了,所以我从来不再作一个类完成类似的操作。另外connection资源一定要用完就关。不要返回ResultSet对象,用RowSet代替。 </div>
<div>-------------------------------------------------------------------------------------<br>我在oracle中,如果不关statement,最后oracle会报错<br>ORA-1000: max cursor exceeded.</div>
<div>可以在 v$open_cursor中查询未关闭的cursor.</div>
<div>最好还是用完就关。 </div>
<div>-------------------------------------------------------------------------------------<br>有一点应该是统一的吧?那就是:当直接connection.close()的时候java端的st对象资源必定已经被释放了,而在DB端相应的cursor资源也许不会马上释放,不同的DB厂商针对这有情况有不同的资源回收策略。 <br>但问题是:是不是正如oldma所说的那样,我们也可以把DB端的资源回收当作黑盒(或者一个能自我调整的容器)来看待,而不必去关心它的溢出或者阻塞???正如我们现在经常使用的连接池pool一样!! <br>1)如果是这样的,那么我们可以只处理connection的关闭,因为connection的关闭会自动引起java端的rs、st和pst的关闭,而在DB端,则有cache可以复用这些未被显式释放的cursor资源,使这些资源不至于被挂起;<br>2)如果不是这样,那么我们必须手工关闭rs、st和pst这些与数据库资源对应的对象来释放DB端的资源,然后在最后关闭conn,因为DB不会聪明地调度这些被挂起的资源,不主动关闭它们会导致DB资源被耗尽。</div>
<div>通过回答这一问题,请大家告诉我,我在发帖的时候写的那个函数在极度频繁被调用时可行吗?因为这个函数不处理任何close()操作,只是根据调用者的connection参数和String参数返回rs给调用者,在调用者的代码的最后会有rs.close()和connection.close()操作,但是肯定不会有st.close()。 那么这个未被显式地close()的st就是我一直不清楚的东西,在非常频繁地被重复这样调用(事实上这样的调用就象out.print()一样多)后,DB端会是怎样一种情况? </div>
<div>-------------------------------------------------------------------------------------<br>对于频繁调用的函数Connecton及Statement绝对要Close,正如其他网友所说,不同的数据库可能有不同的实现,但考虑到重用及数据库的移植等问题,还是Close吧。 </div>
<div>-------------------------------------------------------------------------------------<br>那种方法肯定有问题,不要说服务器端有什么问题,光客户端就可能出现问题,比如一次循环中,你打开很多次的ResultSet和Statement,这个对象不会立刻被释放的。<br>还有我前面说了,几种情况:<br>1、ResultSet不依赖于Connection和Statement,这样你只需要一个Connection和一个Statement,这样你每次可以充用这两个对象,那么你只需要和Connection一样加上对Statement的关闭就可以了,中间的使用者必须自己关闭ResultSet<br>2、ResultSet依赖于Connection和Statement,这样你必须小心设计中间的过程,在同一个命名空间里不能同时建立两个ResultSet对象。<br>3、ResultSet依赖于Statement对象,但不依赖于Connection对象,这样,你不关闭Statement可能和第一种情况下不关闭ResultSet一样。</div>
<div>-------------------------------------------------------------------------------------<br>事先声明一句,我不常写数据库的代码。<br>但是我有个疑惑,根据JAVA DOC,Connection、Statement、ResultSet应该都会在垃圾收集时自动被释放。因此理论上他们不应该会存在资源泄漏问题。可能显式的调用Connection的close能够更快的释放数据库资源,但我认为使用Connection Pool应该是更有效率的做法。但对使用Connection Pool的情况下,是否必须显式的close Connection?Statement和ResultSet应该没有必要显式的释放吧,至少从来没有听说有Statement Pool和ResultSet Pool,这是否意味着他们并不使用DB资源呢?<br>一切只是我的推测,希望有高人能够提出一个可信的测试方案来推翻或是验证它。 </div>
<div>-------------------------------------------------------------------------------------<br>规范说明: connection.close 自动关闭 Statement.close 自动导致 ResultSet 对象无效,注意只是 ResultSet 对象无效,ResultSet 所占用的资源可能还没有释放。所以还是应该显式执行connection、Statement、ResultSet的close方法。特别是在使用connection pool的时候,connection.close 并不会导致物理连接的关闭,不执行ResultSet的close可能会导致更多的资源泄露。</div>
<div>摘录自 JDBC. 3.0 Specification,13.1.3 Closing Statement Objects</div>
<div>An application calls the method Statement.close to indicate that it has finished processing a statement. All Statement objects will be closed when the connection that created them is closed. However, it is good coding practice for applications to close statements as soon as they have finished processing them. This allows any external resources that the statement is using to be released immediately.</div>
<div>Closing a Statement object will close and invalidate any instances of ResultSet produced by that Statement object. The resources held by the ResultSet object may not be released until garbage collection runs again, so it is a good practice to explicitly close ResultSet objects when they are no longer needed.</div>
<div>These comments about closing Statement objects apply to PreparedStatement and CallableStatement objects as well.</div>
<div>-------------------------------------------------------------------------------------<br>我觉得你这个方法这样写才比较合理:</div>
<div>public static ResultSet sysSelect(Connection conn,String sql)throws SQLException{<br>Statement st = null;<br>try{<br>st = conn.createStatement();<br>ResultSet rs = st.executeQuery(sql);<br>return rs;<br>}catch (SQLException ex){<br>throw ex;<br>}finally{<br>if (null!=st) st.close();<br>}<br>} </div>
<div>-------------------------------------------------------------------------------------<br>to glassprogrammer,你说的方法做过测试么,我觉得从原理上说不通。<br>finally中的st.close()会导致它所产生的resultset实例无效,也就是说方法返回参数的rs在该方法执行完毕的时候就是无效的。不知道我的想法对不对。</div>
<div>-------------------------------------------------------------------------------------<br>根据项目中的实际经验,Statement应该显式地关闭,或许与相应的数据库厂商对数据库资源和JDBC驱动实现有各自的不同,为了避免资源没有被及时释放,在connection关闭之前,显式地关闭Statement是必要的。我的做法是将Connection对象做一个包装,实际上是类似proxy,在获取Statement的时候记录其引用,然后在调用Connection的close方法的时候检查记录的引用中的Statement是否已经关闭,如果没有关闭就调用其close方法关闭,根据实际应用的反馈,效果还不错。 </div>
<div>-------------------------------------------------------------------------------------<br>非常感谢大家在这里的建议! 虽然从程序上讲这似乎有点儿钻牛角尖,但这会帮助我理解在高访问频率情况下,代码执行效率的巨大差别! <br>我个人认为:在一个大吞数据吐量和访问率的信息系统中,其健壮性除了使用某种先进的API库或者架构之外,关键之处在于代码的编写习惯、或者是我们经常使用到的、看似可有可无的某些代码的编写方式上!</div>
<div>to glassprogrammer: 关闭连接后还能使用rs的讨论,我在其他地方看到过类似的讨论,可是我以前在DB2、ORACLE812上测试的结果都是行不通的!不知道你是在哪里设置了这一特性? 不过对于使用conn.createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability)的最后一个参数可以做到这一点! 但是这是jdbc3.0里的功能,我现在所在的都是IBM的环境,IBM自带的JDK只相当于sun jre1.3.1的版本,是没有这个功能所以也无法测试。 </div>
<div>-------------------------------------------------------------------------------------<br>根据测试,关不关Statement, ResultSet无所谓,只要Connection关闭,自动就关闭掉前两者,如果说Statement, ResultSet没关闭,会使DB端资源不能释放,但Connection.close()事件里就调用了Statement.close()->ResultSet.close(),你再调用Statement.close(),ResultSet.close()一次干什么了?效果不是一样码?至于cursor,我测试了Oracle,SQL2000,只要Connection.close,Cursor就也自动关闭了.<br>to navyzhu :你肯定其他地方有问题.我做了试验</div>
<div>try{<br>Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");<br>for (int i=0; i<100; i++){<br>Connection conn = DriverManager.getConnection(<br>"jdbc:microsoft:sqlserver://Akun:1433;databaseName=bookstore", "sa",<br>"");<br>Statement stm = conn.createStatement();<br>ResultSet rs = stm.executeQuery("Select * from Book");<br>//stm.close();<br>conn.close();<br>}<br>执行后,在SQL查询分析器里sp_who,不占连接啊. <br>-------------------------------------------------------------------------------------<br>不好意思,实际上Connection.close只是断开同DB的连接,它实际并没去关闭Statement, ResultSet。之所以说Connection.close后,ResultSet无效,是因为ResultSet的操作之前,会检查连接是否有效。所以如next,first等操作都会出错。其他一些跟数据无关的操作就不会有问题。<br>一定要close掉ResultSet,否则资源会泄漏,因为ResultSet里有Stream对象,close才会调用Stream.close。至于mysapphire的问题,一个简单的方法就是再调用一下ResultSet.getStatement().close就可以了。不知道其他高手有何其他高见。</div>
<div>-------------------------------------------------------------------------------------</div>
<div>
<br>前两天两个Bea公司的来做技术支持,说我们的代码有问题导致了内存泄露,让我们在rs.close()和stmt.close()后面一定要加上rs = null和stmt = null。</div>
<div>爆寒! <br>-------------------------------------------------------------------------------------<br>Note: A ResultSet object is automatically closed by the Statement object that generated it when that Statement object is closed, re-executed, or is used to retrieve the next result from a sequence of multiple results. A ResultSet object is also automatically closed when it is garbage collected. </div>
<div>Note: A Statement object is automatically closed when it is garbage collected. When a Statement object is closed, its current ResultSet object, if one exists, is also closed. </div>
<div>Note: A Connection object is automatically closed when it is garbage collected. Certain fatal errors also close a Connection object. </div>
<div>摘自JDK1.4</div>
<div>可见<br>1.垃圾回收机制可以自动关闭它们<br>2.Statement关闭会导致ResultSet关闭<br>3.Connection关闭不会(?)导致Statement关闭<br>4.由于垃圾回收的线程级别是最低的,为了充分利用数据库资源,有必要显式关闭它们,尤其是使用Connection Pool的时候。<br>5.最优经验是按照ResultSet,Statement,Connection的顺序执行close<br>6.如果一定要传递ResultSet,应该使用RowSet,RowSet可以不依赖于Connection和Statement。Java传递的是引用,所以如果传递ResultSet,你会不知道Statement和Connection何时关闭,不知道ResultSet何时有效。</div>
<div>-------------------------------------------------------------------------------------</div>
<div>
<span style="font-family: Arial; font-size: x-small;">我是这样处理的:在 DAO Factory 里放上这个方法。BaseImpl 即所有DAO 接口对象的实现的基类里,调用这个方法。另外还有 getConnection 的。这样,在我的每个 Impl 类中,在用完这些资源后,即 try 的最后,都直接使用 close(rs, pst, conn) 来关闭相关数据库资源(因为是传引用哦,所以我是觉得可以这样来减少代码)。getConnection() 是直接得到连接啦。<br><br>请大家帮我评判一下,这样处理有问题吗?<br><br></span>
<pre>
<strong>public</strong>
<strong>static</strong>
<strong>void</strong> close(java.sql.ResultSet rs,
java.sql.PreparedStatement pst,
java.sql.Connection conn
) {
<strong>if</strong> (rs != <strong>null</strong>) {
<strong>try</strong> {
rs.close();
rs = <strong>null</strong>;
} <strong>catch</strong> (SQLException se) {
se.printStackTrace();
} <strong>finally</strong> {
<strong>if</strong> (rs != <strong>null</strong>) {
<strong>try</strong> {
rs.close();
} <strong>catch</strong> (SQLException se) {
se.printStackTrace();
}
rs = <strong>null</strong>;
}
}
}
<strong>if</strong> (pst != <strong>null</strong>) {
<strong>try</strong> {
pst.close();
pst = <strong>null</strong>;
} <strong>catch</strong> (SQLException ex) {
ex.printStackTrace();
} <strong>finally</strong> {
<strong>if</strong> (pst != <strong>null</strong>) {
<strong>try</strong> {
pst.close();
} <strong>catch</strong> (SQLException se) {
se.printStackTrace();
}
pst = <strong>null</strong>;
}
}
}
<strong>if</strong> (conn != <strong>null</strong>) {
<strong>try</strong> {
conn.close();
conn = <strong>null</strong>;
} <strong>catch</strong> (SQLException ex) {
ex.printStackTrace();
} <strong>finally</strong> {
<strong>if</strong> (conn != <strong>null</strong>) {
<strong>try</strong> {
conn.close();
} <strong>catch</strong> (SQLException se) {
se.printStackTrace();
}
conn = <strong>null</strong>;
}
}
}
}
</code>
上面有人说 close 方法必须放在 <strong>finally</strong> 里,不知道基于什么考虑。
数据库资源与普通 Object 不一样的。应该说建议还是要即时、完全地关闭,也有利于 pooling 来工作。 我想是这样,应该说你的 close() 是由 pooling 的实现来?BR></pre>
</div>
<div>-------------------------------------------------------------------------------------<br>其实好像这是一个很普遍的误解。好多老手,高手,都想当然地rs=null。<br>有些jvm的实现,局部block out of scope时,局部变量引用的对象并没有变成gc'able。<br>不过,函数退出时是没问题的。不需要rs=null</div>
<div>rs=null的不好之处在于,一,麻烦。二,无法用final,而final对提高程序质量还是很有意义的。</div>
<div>对这个资源问题,我前几天在搞vb4(惭愧呀,都老掉牙了!)的时候,也遇到了。惊人地一致,我也是想做这么一个公用函数,来封装常见的stored proc调用。查了好久msdn也没查出个所以然来。测试倒是没问题。好在那个程序就是客户端的,没有server端那么频繁调用。</div>
<div>但是在vb里有问题的,到java里是可以轻松解决的。<br>单纯从问题本身,我认为这是标准所没有规定的。(connection关闭后Statement不可用不表示资源必然被回收)。标准没有的,各个driver的实现就可能不同。所以,无论实验结果如何,都是不可依赖的。<br>解决方法应该是象前面一位老兄说的,自己封装ResultSet。<br>感谢jdbc的设计者,ResultSet是一个接口。我们大可以自己实现ResultSet,在close里面同时关上Statement。</div>
<div>为了避免写好多委托函数的麻烦(ResultSet的方法好多啊!不同的jdbc版本还不一样),可以用dynamic proxy。(具体方法我本来写了一下,但是刚才提交的时候,session timeout,重新登陆后,我写的东西都不见了!懒得再写了)。<br>这样在你最原始的那个函数里,你可以这样用:</div>
<div>Statement stmt = ...;<br><strong>boolean</strong> ok = false;<br><strong>try</strong>{<br> ResultSet rs = ...;<br> ok = <strong>true</strong>;<br> <strong>return</strong> MyResultWrapper.instance(rs,stmt);<br>}<br><strong>finally</strong>{<br> <strong>if</strong>(!ok)stmt.close();<br>}<br><br>不过,越过这个问题本身。我觉得,返回ResultSet也许不总是一个好的选择。为什么不接受一个callback呢?这样,你根本不用要求客户代码记得调用close(),一切你都处理好了。我在以前的一个帖子中也提过这种方法:<br><pre>
<strong>interface</strong> ResultListener{
<strong>public</strong><strong>void</strong> acceptResult(ResultRow rs);
}
<strong>void</strong> populate(ResultListener l){
<strong>final</strong> Statement stmt = ...;
<strong>try</strong>{
<strong>final</strong> ResultSet rs = ...;
<strong>try</strong>{
<strong>while</strong>(...){l.acceptResult(<strong>new</strong> ResultRow(rs));}
}
<strong>finally</strong>{
rs.close();
}
}
<strong>finally</strong>{
stmt.close();
}
}
</pre>
<br>个人觉得,这种方法对不需要update,不需要在result set上随机移动cursor的需求够用了。而且资源管理更健壮。<br><br>
</div>
<div>-------------------------------------------------------------------------------------<br>最好的办法是,在执行Connection类方法close()时,同时关闭Statement,可以考虑使用Delegate模式,以牺牲部分的性能来换取稳定; </div>
<div>-------------------------------------------------------------------------------------<br>我觉得Connection这样的对象本身就是一种封装,不同的厂商实现不同,如果使用了某个厂商的连接池,比如weblogic的,那么Connection.close()并没有释放这个conn,而是将它重新放入池中。因为从datasource中取出的conn实际上是Connection的子类,它覆盖了close()方法。具体可以查看相关厂商提供的文档。</div>
<div>我想这是为何有的人一定要显示关闭statement,有的人又发现不显示关闭statement也可以的原因吧。<br>
</div>
<div class="postfoot">posted on 2006-09-01 09:37 <a href="http://www.blogjava.net/fantasy/"><span style="color: #000080;">Web 2.0 技术资源</span></a> 阅读(2677) <a href="http://mzhj.iteye.com/admin/blogs/#Post"><span style="color: #000080;">评论(2)</span></a> <a href="http://www.blogjava.net/fantasy/admin/EditPosts.aspx?postid=67012"><span style="color: #000080;">编辑</span></a> <a href="http://www.blogjava.net/fantasy/AddToFavorite.aspx?id=67012"><span style="color: #000080;">收藏</span></a> 所属分类: <a href="http://www.blogjava.net/fantasy/category/8565.html"><span style="color: #000080;">数据库</span></a> </div>
<p><img src="http://www.blogjava.net/fantasy/aggbug/67012.html?webview=1" alt="" width="1" height="1"></p>
<!--
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
<rdf:Description
rdf:about="http://www.blogjava.net/fantasy/archive/2006/09/01/67012.html"
dc:identifier="http://www.blogjava.net/fantasy/archive/2006/09/01/67012.html"
dc:title="关于 JDBC 资源回收的讨论 !"
trackback:ping="http://www.blogjava.net/fantasy/services/trackbacks/67012.aspx" />
</rdf:RDF>
-->
<p>
<script type="text/javascript"></script></p>
<div id="AjaxHolder_UpdatePanel1">
<a name="pagedcomment"></a><a name="%E8%AF%84%E8%AE%BA"><br><div id="comments">
<h3>评论</h3>
<div class="post">
<div class="postTitle"></div>
<div class="postText">我觉得我页应该说两句,一般我们都是在一个程序里面使用一个conn,多个stmt,多个rs.所以保证了在一个程序的conn的获得和释放是一致的.~但是rs和stmt一般都没处理~~看来我埋下了一颗定时炸 8弹啊~~ <br>ps,哪里又比较系统的关于Statement和ResultSet的资料? <a href="http://mzhj.iteye.com/fantasy/archive/2006/09/01/67012.html#post"><span style="color: #000080;">回复</span></a> <a title="查看该作者发表过的评论" href="http://www.blogjava.net/comment?author=%eb%b0%94%eb%b3%b4" target="_blank"><span style="color: #000080;">更多评论</span></a> <br><a id="AjaxHolder_Comments_CommentList_ctl00_DeleteLink"></a> <a id="AjaxHolder_Comments_CommentList_ctl00_EditLink"></a> </div>
</div>
<br>
</div>
</a><a title="permalink: re: 关于 JDBC 资源回收的讨论 !" href="http://mzhj.iteye.com/fantasy/archive/2006/09/01/67012.html#67040"><span style="color: #000080;">#</span></a> <a name="67040"></a>re: 关于 JDBC 资源回收的讨论 ! <span>2006-09-01 11:04 </span><a id="AjaxHolder_Comments_CommentList_ctl00_NameLink" href="http://roddeck1982.spaces.live.com/" target="_blank"><span style="color: #000080;">바보</span></a> </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>> 你是说:在有的时候就算是释放了connection也可能有部分的<br>> 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肯定都是关闭了得,但是资源还没有释放阿。如果从性能方面考虑的话,一定的明显的关闭Statement,ResultSet,还有两点需要注意:<br>1,不要隐式产生Statement,ResultSet对象<br>2,关闭对象一定要在finally中关闭 </div>
<div>-------------------------------------------------------------------------------------<br>JDBC3.0规范中提出了一个新的规范:把Statement也进行缓存(一般是应用服务器厂商实现),这样就可以在不同的connection之间可以共享Statement。所以我个人以为,在释放connection之前,最好先close Statement,这样有利于statement的重用(而且这也是规范所推荐的比较好的编程习惯)。 </div>
<div>-------------------------------------------------------------------------------------<br>Statement和PreparedStatement已经将数据库操作封装的很好了,所以我从来不再作一个类完成类似的操作。另外connection资源一定要用完就关。不要返回ResultSet对象,用RowSet代替。 </div>
<div>-------------------------------------------------------------------------------------<br>我在oracle中,如果不关statement,最后oracle会报错<br>ORA-1000: max cursor exceeded.</div>
<div>可以在 v$open_cursor中查询未关闭的cursor.</div>
<div>最好还是用完就关。 </div>
<div>-------------------------------------------------------------------------------------<br>有一点应该是统一的吧?那就是:当直接connection.close()的时候java端的st对象资源必定已经被释放了,而在DB端相应的cursor资源也许不会马上释放,不同的DB厂商针对这有情况有不同的资源回收策略。 <br>但问题是:是不是正如oldma所说的那样,我们也可以把DB端的资源回收当作黑盒(或者一个能自我调整的容器)来看待,而不必去关心它的溢出或者阻塞???正如我们现在经常使用的连接池pool一样!! <br>1)如果是这样的,那么我们可以只处理connection的关闭,因为connection的关闭会自动引起java端的rs、st和pst的关闭,而在DB端,则有cache可以复用这些未被显式释放的cursor资源,使这些资源不至于被挂起;<br>2)如果不是这样,那么我们必须手工关闭rs、st和pst这些与数据库资源对应的对象来释放DB端的资源,然后在最后关闭conn,因为DB不会聪明地调度这些被挂起的资源,不主动关闭它们会导致DB资源被耗尽。</div>
<div>通过回答这一问题,请大家告诉我,我在发帖的时候写的那个函数在极度频繁被调用时可行吗?因为这个函数不处理任何close()操作,只是根据调用者的connection参数和String参数返回rs给调用者,在调用者的代码的最后会有rs.close()和connection.close()操作,但是肯定不会有st.close()。 那么这个未被显式地close()的st就是我一直不清楚的东西,在非常频繁地被重复这样调用(事实上这样的调用就象out.print()一样多)后,DB端会是怎样一种情况? </div>
<div>-------------------------------------------------------------------------------------<br>对于频繁调用的函数Connecton及Statement绝对要Close,正如其他网友所说,不同的数据库可能有不同的实现,但考虑到重用及数据库的移植等问题,还是Close吧。 </div>
<div>-------------------------------------------------------------------------------------<br>那种方法肯定有问题,不要说服务器端有什么问题,光客户端就可能出现问题,比如一次循环中,你打开很多次的ResultSet和Statement,这个对象不会立刻被释放的。<br>还有我前面说了,几种情况:<br>1、ResultSet不依赖于Connection和Statement,这样你只需要一个Connection和一个Statement,这样你每次可以充用这两个对象,那么你只需要和Connection一样加上对Statement的关闭就可以了,中间的使用者必须自己关闭ResultSet<br>2、ResultSet依赖于Connection和Statement,这样你必须小心设计中间的过程,在同一个命名空间里不能同时建立两个ResultSet对象。<br>3、ResultSet依赖于Statement对象,但不依赖于Connection对象,这样,你不关闭Statement可能和第一种情况下不关闭ResultSet一样。</div>
<div>-------------------------------------------------------------------------------------<br>事先声明一句,我不常写数据库的代码。<br>但是我有个疑惑,根据JAVA DOC,Connection、Statement、ResultSet应该都会在垃圾收集时自动被释放。因此理论上他们不应该会存在资源泄漏问题。可能显式的调用Connection的close能够更快的释放数据库资源,但我认为使用Connection Pool应该是更有效率的做法。但对使用Connection Pool的情况下,是否必须显式的close Connection?Statement和ResultSet应该没有必要显式的释放吧,至少从来没有听说有Statement Pool和ResultSet Pool,这是否意味着他们并不使用DB资源呢?<br>一切只是我的推测,希望有高人能够提出一个可信的测试方案来推翻或是验证它。 </div>
<div>-------------------------------------------------------------------------------------<br>规范说明: connection.close 自动关闭 Statement.close 自动导致 ResultSet 对象无效,注意只是 ResultSet 对象无效,ResultSet 所占用的资源可能还没有释放。所以还是应该显式执行connection、Statement、ResultSet的close方法。特别是在使用connection pool的时候,connection.close 并不会导致物理连接的关闭,不执行ResultSet的close可能会导致更多的资源泄露。</div>
<div>摘录自 JDBC. 3.0 Specification,13.1.3 Closing Statement Objects</div>
<div>An application calls the method Statement.close to indicate that it has finished processing a statement. All Statement objects will be closed when the connection that created them is closed. However, it is good coding practice for applications to close statements as soon as they have finished processing them. This allows any external resources that the statement is using to be released immediately.</div>
<div>Closing a Statement object will close and invalidate any instances of ResultSet produced by that Statement object. The resources held by the ResultSet object may not be released until garbage collection runs again, so it is a good practice to explicitly close ResultSet objects when they are no longer needed.</div>
<div>These comments about closing Statement objects apply to PreparedStatement and CallableStatement objects as well.</div>
<div>-------------------------------------------------------------------------------------<br>我觉得你这个方法这样写才比较合理:</div>
<div>public static ResultSet sysSelect(Connection conn,String sql)throws SQLException{<br>Statement st = null;<br>try{<br>st = conn.createStatement();<br>ResultSet rs = st.executeQuery(sql);<br>return rs;<br>}catch (SQLException ex){<br>throw ex;<br>}finally{<br>if (null!=st) st.close();<br>}<br>} </div>
<div>-------------------------------------------------------------------------------------<br>to glassprogrammer,你说的方法做过测试么,我觉得从原理上说不通。<br>finally中的st.close()会导致它所产生的resultset实例无效,也就是说方法返回参数的rs在该方法执行完毕的时候就是无效的。不知道我的想法对不对。</div>
<div>-------------------------------------------------------------------------------------<br>根据项目中的实际经验,Statement应该显式地关闭,或许与相应的数据库厂商对数据库资源和JDBC驱动实现有各自的不同,为了避免资源没有被及时释放,在connection关闭之前,显式地关闭Statement是必要的。我的做法是将Connection对象做一个包装,实际上是类似proxy,在获取Statement的时候记录其引用,然后在调用Connection的close方法的时候检查记录的引用中的Statement是否已经关闭,如果没有关闭就调用其close方法关闭,根据实际应用的反馈,效果还不错。 </div>
<div>-------------------------------------------------------------------------------------<br>非常感谢大家在这里的建议! 虽然从程序上讲这似乎有点儿钻牛角尖,但这会帮助我理解在高访问频率情况下,代码执行效率的巨大差别! <br>我个人认为:在一个大吞数据吐量和访问率的信息系统中,其健壮性除了使用某种先进的API库或者架构之外,关键之处在于代码的编写习惯、或者是我们经常使用到的、看似可有可无的某些代码的编写方式上!</div>
<div>to glassprogrammer: 关闭连接后还能使用rs的讨论,我在其他地方看到过类似的讨论,可是我以前在DB2、ORACLE812上测试的结果都是行不通的!不知道你是在哪里设置了这一特性? 不过对于使用conn.createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability)的最后一个参数可以做到这一点! 但是这是jdbc3.0里的功能,我现在所在的都是IBM的环境,IBM自带的JDK只相当于sun jre1.3.1的版本,是没有这个功能所以也无法测试。 </div>
<div>-------------------------------------------------------------------------------------<br>根据测试,关不关Statement, ResultSet无所谓,只要Connection关闭,自动就关闭掉前两者,如果说Statement, ResultSet没关闭,会使DB端资源不能释放,但Connection.close()事件里就调用了Statement.close()->ResultSet.close(),你再调用Statement.close(),ResultSet.close()一次干什么了?效果不是一样码?至于cursor,我测试了Oracle,SQL2000,只要Connection.close,Cursor就也自动关闭了.<br>to navyzhu :你肯定其他地方有问题.我做了试验</div>
<div>try{<br>Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");<br>for (int i=0; i<100; i++){<br>Connection conn = DriverManager.getConnection(<br>"jdbc:microsoft:sqlserver://Akun:1433;databaseName=bookstore", "sa",<br>"");<br>Statement stm = conn.createStatement();<br>ResultSet rs = stm.executeQuery("Select * from Book");<br>//stm.close();<br>conn.close();<br>}<br>执行后,在SQL查询分析器里sp_who,不占连接啊. <br>-------------------------------------------------------------------------------------<br>不好意思,实际上Connection.close只是断开同DB的连接,它实际并没去关闭Statement, ResultSet。之所以说Connection.close后,ResultSet无效,是因为ResultSet的操作之前,会检查连接是否有效。所以如next,first等操作都会出错。其他一些跟数据无关的操作就不会有问题。<br>一定要close掉ResultSet,否则资源会泄漏,因为ResultSet里有Stream对象,close才会调用Stream.close。至于mysapphire的问题,一个简单的方法就是再调用一下ResultSet.getStatement().close就可以了。不知道其他高手有何其他高见。</div>
<div>-------------------------------------------------------------------------------------</div>
<div>
<br>前两天两个Bea公司的来做技术支持,说我们的代码有问题导致了内存泄露,让我们在rs.close()和stmt.close()后面一定要加上rs = null和stmt = null。</div>
<div>爆寒! <br>-------------------------------------------------------------------------------------<br>Note: A ResultSet object is automatically closed by the Statement object that generated it when that Statement object is closed, re-executed, or is used to retrieve the next result from a sequence of multiple results. A ResultSet object is also automatically closed when it is garbage collected. </div>
<div>Note: A Statement object is automatically closed when it is garbage collected. When a Statement object is closed, its current ResultSet object, if one exists, is also closed. </div>
<div>Note: A Connection object is automatically closed when it is garbage collected. Certain fatal errors also close a Connection object. </div>
<div>摘自JDK1.4</div>
<div>可见<br>1.垃圾回收机制可以自动关闭它们<br>2.Statement关闭会导致ResultSet关闭<br>3.Connection关闭不会(?)导致Statement关闭<br>4.由于垃圾回收的线程级别是最低的,为了充分利用数据库资源,有必要显式关闭它们,尤其是使用Connection Pool的时候。<br>5.最优经验是按照ResultSet,Statement,Connection的顺序执行close<br>6.如果一定要传递ResultSet,应该使用RowSet,RowSet可以不依赖于Connection和Statement。Java传递的是引用,所以如果传递ResultSet,你会不知道Statement和Connection何时关闭,不知道ResultSet何时有效。</div>
<div>-------------------------------------------------------------------------------------</div>
<div>
<span style="font-family: Arial; font-size: x-small;">我是这样处理的:在 DAO Factory 里放上这个方法。BaseImpl 即所有DAO 接口对象的实现的基类里,调用这个方法。另外还有 getConnection 的。这样,在我的每个 Impl 类中,在用完这些资源后,即 try 的最后,都直接使用 close(rs, pst, conn) 来关闭相关数据库资源(因为是传引用哦,所以我是觉得可以这样来减少代码)。getConnection() 是直接得到连接啦。<br><br>请大家帮我评判一下,这样处理有问题吗?<br><br></span>
<pre>
<strong>public</strong>
<strong>static</strong>
<strong>void</strong> close(java.sql.ResultSet rs,
java.sql.PreparedStatement pst,
java.sql.Connection conn
) {
<strong>if</strong> (rs != <strong>null</strong>) {
<strong>try</strong> {
rs.close();
rs = <strong>null</strong>;
} <strong>catch</strong> (SQLException se) {
se.printStackTrace();
} <strong>finally</strong> {
<strong>if</strong> (rs != <strong>null</strong>) {
<strong>try</strong> {
rs.close();
} <strong>catch</strong> (SQLException se) {
se.printStackTrace();
}
rs = <strong>null</strong>;
}
}
}
<strong>if</strong> (pst != <strong>null</strong>) {
<strong>try</strong> {
pst.close();
pst = <strong>null</strong>;
} <strong>catch</strong> (SQLException ex) {
ex.printStackTrace();
} <strong>finally</strong> {
<strong>if</strong> (pst != <strong>null</strong>) {
<strong>try</strong> {
pst.close();
} <strong>catch</strong> (SQLException se) {
se.printStackTrace();
}
pst = <strong>null</strong>;
}
}
}
<strong>if</strong> (conn != <strong>null</strong>) {
<strong>try</strong> {
conn.close();
conn = <strong>null</strong>;
} <strong>catch</strong> (SQLException ex) {
ex.printStackTrace();
} <strong>finally</strong> {
<strong>if</strong> (conn != <strong>null</strong>) {
<strong>try</strong> {
conn.close();
} <strong>catch</strong> (SQLException se) {
se.printStackTrace();
}
conn = <strong>null</strong>;
}
}
}
}
</code>
上面有人说 close 方法必须放在 <strong>finally</strong> 里,不知道基于什么考虑。
数据库资源与普通 Object 不一样的。应该说建议还是要即时、完全地关闭,也有利于 pooling 来工作。 我想是这样,应该说你的 close() 是由 pooling 的实现来?BR></pre>
</div>
<div>-------------------------------------------------------------------------------------<br>其实好像这是一个很普遍的误解。好多老手,高手,都想当然地rs=null。<br>有些jvm的实现,局部block out of scope时,局部变量引用的对象并没有变成gc'able。<br>不过,函数退出时是没问题的。不需要rs=null</div>
<div>rs=null的不好之处在于,一,麻烦。二,无法用final,而final对提高程序质量还是很有意义的。</div>
<div>对这个资源问题,我前几天在搞vb4(惭愧呀,都老掉牙了!)的时候,也遇到了。惊人地一致,我也是想做这么一个公用函数,来封装常见的stored proc调用。查了好久msdn也没查出个所以然来。测试倒是没问题。好在那个程序就是客户端的,没有server端那么频繁调用。</div>
<div>但是在vb里有问题的,到java里是可以轻松解决的。<br>单纯从问题本身,我认为这是标准所没有规定的。(connection关闭后Statement不可用不表示资源必然被回收)。标准没有的,各个driver的实现就可能不同。所以,无论实验结果如何,都是不可依赖的。<br>解决方法应该是象前面一位老兄说的,自己封装ResultSet。<br>感谢jdbc的设计者,ResultSet是一个接口。我们大可以自己实现ResultSet,在close里面同时关上Statement。</div>
<div>为了避免写好多委托函数的麻烦(ResultSet的方法好多啊!不同的jdbc版本还不一样),可以用dynamic proxy。(具体方法我本来写了一下,但是刚才提交的时候,session timeout,重新登陆后,我写的东西都不见了!懒得再写了)。<br>这样在你最原始的那个函数里,你可以这样用:</div>
<div>Statement stmt = ...;<br><strong>boolean</strong> ok = false;<br><strong>try</strong>{<br> ResultSet rs = ...;<br> ok = <strong>true</strong>;<br> <strong>return</strong> MyResultWrapper.instance(rs,stmt);<br>}<br><strong>finally</strong>{<br> <strong>if</strong>(!ok)stmt.close();<br>}<br><br>不过,越过这个问题本身。我觉得,返回ResultSet也许不总是一个好的选择。为什么不接受一个callback呢?这样,你根本不用要求客户代码记得调用close(),一切你都处理好了。我在以前的一个帖子中也提过这种方法:<br><pre>
<strong>interface</strong> ResultListener{
<strong>public</strong><strong>void</strong> acceptResult(ResultRow rs);
}
<strong>void</strong> populate(ResultListener l){
<strong>final</strong> Statement stmt = ...;
<strong>try</strong>{
<strong>final</strong> ResultSet rs = ...;
<strong>try</strong>{
<strong>while</strong>(...){l.acceptResult(<strong>new</strong> ResultRow(rs));}
}
<strong>finally</strong>{
rs.close();
}
}
<strong>finally</strong>{
stmt.close();
}
}
</pre>
<br>个人觉得,这种方法对不需要update,不需要在result set上随机移动cursor的需求够用了。而且资源管理更健壮。<br><br>
</div>
<div>-------------------------------------------------------------------------------------<br>最好的办法是,在执行Connection类方法close()时,同时关闭Statement,可以考虑使用Delegate模式,以牺牲部分的性能来换取稳定; </div>
<div>-------------------------------------------------------------------------------------<br>我觉得Connection这样的对象本身就是一种封装,不同的厂商实现不同,如果使用了某个厂商的连接池,比如weblogic的,那么Connection.close()并没有释放这个conn,而是将它重新放入池中。因为从datasource中取出的conn实际上是Connection的子类,它覆盖了close()方法。具体可以查看相关厂商提供的文档。</div>
<div>我想这是为何有的人一定要显示关闭statement,有的人又发现不显示关闭statement也可以的原因吧。<br>
</div>
<div class="postfoot">posted on 2006-09-01 09:37 <a href="http://www.blogjava.net/fantasy/"><span style="color: #000080;">Web 2.0 技术资源</span></a> 阅读(2677) <a href="http://mzhj.iteye.com/admin/blogs/#Post"><span style="color: #000080;">评论(2)</span></a> <a href="http://www.blogjava.net/fantasy/admin/EditPosts.aspx?postid=67012"><span style="color: #000080;">编辑</span></a> <a href="http://www.blogjava.net/fantasy/AddToFavorite.aspx?id=67012"><span style="color: #000080;">收藏</span></a> 所属分类: <a href="http://www.blogjava.net/fantasy/category/8565.html"><span style="color: #000080;">数据库</span></a> </div>
<p><img src="http://www.blogjava.net/fantasy/aggbug/67012.html?webview=1" alt="" width="1" height="1"></p>
<!--
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
<rdf:Description
rdf:about="http://www.blogjava.net/fantasy/archive/2006/09/01/67012.html"
dc:identifier="http://www.blogjava.net/fantasy/archive/2006/09/01/67012.html"
dc:title="关于 JDBC 资源回收的讨论 !"
trackback:ping="http://www.blogjava.net/fantasy/services/trackbacks/67012.aspx" />
</rdf:RDF>
-->
<p>
<script type="text/javascript"></script></p>
<div id="AjaxHolder_UpdatePanel1">
<a name="pagedcomment"></a><a name="%E8%AF%84%E8%AE%BA"><br><div id="comments">
<h3>评论</h3>
<div class="post">
<div class="postTitle"></div>
<div class="postText">我觉得我页应该说两句,一般我们都是在一个程序里面使用一个conn,多个stmt,多个rs.所以保证了在一个程序的conn的获得和释放是一致的.~但是rs和stmt一般都没处理~~看来我埋下了一颗定时炸 8弹啊~~ <br>ps,哪里又比较系统的关于Statement和ResultSet的资料? <a href="http://mzhj.iteye.com/fantasy/archive/2006/09/01/67012.html#post"><span style="color: #000080;">回复</span></a> <a title="查看该作者发表过的评论" href="http://www.blogjava.net/comment?author=%eb%b0%94%eb%b3%b4" target="_blank"><span style="color: #000080;">更多评论</span></a> <br><a id="AjaxHolder_Comments_CommentList_ctl00_DeleteLink"></a> <a id="AjaxHolder_Comments_CommentList_ctl00_EditLink"></a> </div>
</div>
<br>
</div>
</a><a title="permalink: re: 关于 JDBC 资源回收的讨论 !" href="http://mzhj.iteye.com/fantasy/archive/2006/09/01/67012.html#67040"><span style="color: #000080;">#</span></a> <a name="67040"></a>re: 关于 JDBC 资源回收的讨论 ! <span>2006-09-01 11:04 </span><a id="AjaxHolder_Comments_CommentList_ctl00_NameLink" href="http://roddeck1982.spaces.live.com/" target="_blank"><span style="color: #000080;">바보</span></a> </div>
相关推荐
这里我们主要讨论Microsoft官方的SQL Server JDBC Driver,它同样实现了JDBC接口,适用于与SQL Server数据库的交互。 #### 使用步骤 1. **获取驱动**:可以从Microsoft官网下载sqljdbc_auth.dll和sqljdbc.jar文件...
3. **连接池支持**:JDBC 4增强了对连接池的内置支持,简化了连接管理和资源回收。 4. **新API和功能**:如`Connection.isValid(int timeout)`方法用于检测数据库连接是否有效,以及`Statement.getGeneratedKeys()`...
接着,我们讨论连接池的概念。在Java中,有多个流行的连接池实现,如C3P0、HikariCP和Apache DBCP。这些库管理数据库连接的生命周期,提供高效的连接复用。在本例中,我们有一个自定义的简单连接池类,它可能包含...
当我们谈论“jdbc优化连接数据库”时,主要涉及提高数据库访问性能、减少资源消耗以及提升系统稳定性。下面将详细讨论优化MySQL数据库连接的代码和开发步骤。 1. **连接池的使用**: - 连接池是管理数据库连接的...
3. **封装、继承和多态**:这是面向对象编程的三大特性,面试时会深入讨论它们的概念和实际应用。 4. **异常处理**:理解如何使用try-catch-finally语句块,以及throw和throws关键字的区别。 5. **垃圾回收机制**...
在JDBC中,我们通常需要经历五个步骤:获取数据源、获取连接、获取执行器(Statement、PreparedStatement或CallableStatement)、执行SQL操作以及关闭资源。其中,PreparedStatement是最常用的执行器,它支持预编译...
8. **JDBC与数据库连接**:Java数据库连接(JDBC)是访问数据库的标准API,文档会介绍如何建立数据库连接、执行SQL语句、处理结果集等。 9. **Spring框架**:Spring是Java企业级应用开发中最常用的框架,可能包含...
下面将详细讨论这两种数据源的配置和特性。 **DBCP数据源配置** Apache的DBCP是一个基于Jakarta Commons Pool的对象池机制的数据库连接池。要配置DBCP,首先需要将`jakarta-commons/commons-dbcp.jar`和`jakarta-...
首先,关于C3P0的基础知识,它是由Miquel Arquero开发的一个开源项目,它提供了数据库连接池的功能,支持JDBC,能够自动管理数据库连接的创建、分配、回收和关闭,避免了频繁地创建和关闭连接带来的系统开销。...
这里我们主要讨论四个知名的Java数据库连接池库:C3P0、DBCP、DBUtils和Druid。 首先,C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。C3P0的主要特性包括连接测试、自动...
在IT行业中,数据库连接池是优化数据库访问性能和资源管理的重要技术。连接池允许应用程序重复使用已建立的数据库连接,避免频繁创建和销毁连接带来的性能开销。在本主题中,我们将深入探讨Tomcat服务器中不同版本的...
在Java开发中,数据库连接管理是一项关键任务,因为它直接影响到应用程序的性能和资源利用效率。c3p0和MySQL Connector/J是两个非常重要的组件,它们在这个领域起着至关重要的作用。这里我们主要讨论这两个jar包的...
【标题】:“Java Hibernate C3P0”是一个关于Java编程中的持久化框架Hibernate与C3P0连接池的讨论。Hibernate是Java领域广泛使用的对象关系映射(ORM)框架,它简化了数据库操作,使开发者可以使用面向对象的方式来...
#### 一、关于本教程 本教程主要介绍Java线程的基础知识,包括线程的概念、为什么线程有用以及如何开始编写简单的多线程程序。此外,还将探讨更复杂的线程应用程序的基本构建块,如线程间的数据交换、线程控制及...
在IT行业中,数据库连接池是优化Web应用性能和资源管理的关键技术之一,尤其是在使用Java Server Pages (JSP) 进行动态网页开发时。本文将深入探讨JSP中数据库连接池的概念、工作原理以及如何实现它,同时结合提供的...
论坛上会有许多关于如何提高应用性能、降低资源消耗的讨论,包括代码优化、数据库查询优化、服务器配置调优等。 10. **分布式与微服务** 随着技术的发展,分布式系统和微服务架构逐渐成为热点。Docker、...
这个压缩包“JAVA 编程 API基础 JAVA开发平台,JAVA编程资源----JAVA API.zip”显然包含了关于Java API的基础知识和相关资源,非常适合初学者或希望深入理解Java API的开发者。 Java API基础.doc很可能是文档形式的...
此外,Java的内存管理和垃圾回收机制也可能进行了优化,以适应现代多核处理器的环境,正如主持人提到的,未来处理器的核心数量将会显著增长,这对Java的并发处理能力和资源管理提出了更高的要求。 在Oracle数据库...
这里我们主要讨论Tomcat JDBC Pool,它具有更好的性能和更丰富的特性。 在Tomcat中,配置连接池通常分为两步:第一步是在`context.xml`文件中全局配置连接池,第二步是在`web.xml`文件中为每个Web应用指定使用该...