首页 > 技术文章 > JDBC,ResultSet对像多次使用后再关闭的问题

doudou-taste 2018-05-10 17:04 原文

原文链接:https://yq.aliyun.com/wenzhang/show_111763

 

问题描述

 1 //代码...
 2 
 3 ResultSet rs = this.conn.prepareStatement("select * from test1").executeQuery();
 4 
 5 //注sql语句不同
 6 
 7 while(rs.next()){  ...}
 8 
 9 rs = this.conn.prepareStatement("select * from test2").executeQuery();
10 
11 //注sql语句不同
12 
13 while(rs.next()){  ...}
14 
15 rs = this.conn.prepareStatement("select * from test3").executeQuery();
16 
17 //注sql语句不同
18 
19 while(rs.next()){  ...}
20 
21 rs.getStatement().close();

//疑问1:多次使用rs对象后,我在最后关闭一次,这样有没有问题?还是要每次用完都关闭(如上代码要关3次rs?)

//疑问2:使用rs.getStatement().close();关闭前,有没有必要先使用rs.close();关闭,每次都是吗(如上代码要关3次rs?)?

 

高手回答:

  

解决方案

  正常情况下如果使用Statement执行完一个查询,又去执行另一个查询时这时候第一个查询的结果集就会被关闭,也就是说,所有的Statement的查询对应的结果集是一个,如果调用Connection的commit()方法也会关闭结果集。可保持性就是指当ResultSet的结果被提交时,是被关闭还是不被关闭。JDBC2.0和1.0提供的都是提交后ResultSet就会被关闭。不过在JDBC3.0中,我们可以设置ResultSet是否关闭。要完成这样的ResultSet的对象的创建,要使用的Statement的创建要具有三个参数,这个Statement的创建方式也就是,我所说的Statement的第三种创建方式。如下:Statement st=createStatement(int resultsetscrollable,int resultsetupdateable,int resultsetSetHoldability)ResultSet rs = st.excuteQuery(sqlStr);前两个参数和两个参数的createStatement方法中的参数是完全相同的,这里只介绍第三个参数: resultSetHoldability表示在结果集提交后结果集是否打开,取值有两个: ResultSet.HOLD_CURSORS_OVER_COMMIT:表示修改提交时,不关闭数据库。 ResultSet.CLOSE_CURSORS_AT_COMMIT:表示修改提交时ResultSet关闭。
解决方案二:
  所以对于你的疑问要看具体的情况,一般情况下是没错的,不过为了便于阅读和理解程序,我们习惯还是最好关闭,如果是多个记录集最好是对应多个Statement
解决方案三:
  引用每次用完都关闭的话,它会立即释放此 ResultSet 对象的数据库和 JDBC 资源 如果在最后关闭的话,只是释放了最后这次查询的ResultSet,JDBC 资源. 如果不关闭的话,就会等待该对象自动关闭时(垃圾收集)发生释放此 ResultSet 对象的数据库和 JDBC 资源此操作。 rs.getStatement().close();自动导致ResultSet对象无效 注意只是ResultSet对象无效,ResultSet所占用的资源可能还没有释放,所有最好还是调有rs.close() 不执行ResultSet的close可能会导致更多的资源泄露

 

  SUN: 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. 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. These comments about closing Statement objects apply to PreparedStatement and CallableStatement objects as well.

疑问:

  上面这位老兄说的我有点不赞同,我们可以写一个程序来测试一下,

 

rs=stmt.executeQuery("select * from test1 ");
rs2=stmt.executeQuery("select * from test2 ");

while(rs2.next()){
System.out.println(rs2.getString(1));
System.out.println(rs2.getString(2));}

while(rs.next()){
System.out.println(rs.getString(1));
System.out.println(rs.getString(2));
}  

  前面和后面我都不写了,假如你用这个测试的,会直接报Operation not allowed after ResultSet closed,那从这个异常我们就可以看出,在你进行操作的时候,你前一个rs已经被自动关闭了,所以说是“正常情况下如果使用Statement执行完一个查询,又去执行另一个查询时这时候第一个查询的结果集就会被关闭”。
解决方案四:
  每次用完都关闭的话,它会立即释放此 ResultSet 对象的数据库和 JDBC 资源如果在最后关闭的话,只是释放了最后这次查询的ResultSet,JDBC 资源.如果不关闭的话,就会等待该对象自动关闭时(垃圾收集)发生释放此 ResultSet 对象的数据库和 JDBC 资源此操作。 rs.getStatement().close();自动导致ResultSet对象无效 注意只是ResultSet对象无效,ResultSet所占用的资源可能还没有释放,所有最好还是调有rs.close()不执行ResultSet的close可能会导致更多的资源泄露。

 SUN: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. 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. These comments about closing Statement objects apply to PreparedStatement and CallableStatement objects as well.

 

推荐阅读