请问各位,如何关闭JDBC中一个connection的所有resultset和statement我知道直接关闭connection也可以实现,但是因为我的程序需要不停的操作数据库,是一个电信项目,所以connection要一直保持,不去关闭它,不然开销太大,而且因为需要频繁的创建resultset和statement,如果一个个关闭太麻烦了,能否在一个操作循环完后,在一个地方关闭掉一个connection的所有resultset和statement呢?

解决方案 »

  1.   

    在finally里关resultset和statement不可以?
      

  2.   

    页面上:
    resultset.close();
     resultset=null;
     (statement) :opa
     opa.free();
    在连接库的类里面:
    // 进行数据库连接释放
    public boolean free() {
    try {
    count--; if (stmt != null) {
    if (!stmt.getConnection().isClosed()) {
    stmt.close();

    } }
    if (connect != null) {
    if (!connect.isClosed())
    connect.close();
    }
    return true;
    } catch (Exception e) {
    return false;
    } }
      

  3.   

    一种是通过项目组内部开发约束,约束你的开发人员用完statement、resultset之后必须在finally中关闭;第二种方式是对操作数据库的方式都用Template Design Pattern封闭,类似Spring的JdbcTemplate那样,开发人员不用编写大量重复的关闭代码第三种方式可以通过Adapter模式二次封装特定的JDBC包的Connection、Statement对象,实现Connection、Statement接口,分别让你的statement、resultset对象在Connection、Statement中可控制,比如Connection发放得一个Statement对象时,在你自定义的Connection类对象中可以保留一个这个对象的引用
    , 之后可以通过调用方法connection.closeAllStatement(),遍历你所发放在外的Statement,对其发放在外的resultset对象关闭,之后再关闭自身,这样就能达到你所要的效果。也可以调用调用statement.closeAllResultset()对象来关闭这个statement发放在外的所有的resultset对象了。
      

  4.   

    还是J2SE / 基础类的人比较好啊,这个问题刚开始发到J2SE / 扩展类好几天都没人回复,可能这个问题太简单?J2SE / 扩展类里的高人都不屑回答?to gongyali2005(JAVA 民工)
    你说的我试过,但是有问题
    我之前发过这个问题,但是一直没有得到满意的答案,所以我就换了个问题,贴下之前的那个问题,其实现在这个问题就是因为要解决那个问题的
    最近在做的一个程序,遇到了一个JDBC方面的问题,我的代码如下
     public  ResultSet  executeSql(String sqlstr)
      {
         Statement stmt = null;
         ResultSet  rs = null;     try
         {
           stmt=conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
           rs=stmt.executeQuery(sqlstr);
           DebugLog.logger.log(Level.INFO,"获取数据集成功");
           return rs;
         }
         catch(SQLException e)
         {
           DebugLog.logger.log(Level.WARNING,"获取数据集时出现错误");
           DebugLog.logger.log(Level.WARNING,e.getMessage());
           try{
           conn.rollback();
           }
           catch(SQLException i)
       {
           DebugLog.logger.log(Level.WARNING,"回滚数据集时出现错误");
           DebugLog.logger.log(Level.WARNING,i.getMessage());
       }
           return null;
         }
         catch(Exception cnfe){
         DebugLog.logger.log(Level.WARNING,"获取数据集时出现错误");
         DebugLog.logger.log(Level.WARNING,cnfe.getMessage());
         return null;
         }  }
    这是我之前写的一段JDBC操作数据库的代码,但是主程序运行一段时间出现这样的异常ora-01000: maximum open cursors exceeded.到网上查了下,说是已经达到一个进程打开的最大游标数,Java代码在执行conn.createStatement()和conn.prepareStatement()的时候,实际上都是相当与在数据库中打开了一个cursor。
    尤其是,如果你的createStatement和prepareStatement是在一个循环里面的话,就会非常容易出现这个问题。因为游标一直在不停的打开,而且没有关闭,所以说,最好在执行了一次executeQuery、executeUpdate等之后,如果不需要使用结果集(ResultSet)的数据,就马上将Statment关闭。然后我的代码改进如下
     public  ResultSet  executeSql(String sqlstr)
      {
         Statement stmt = null;
         ResultSet  rs = null;     try
         {
           stmt=conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
           rs=stmt.executeQuery(sqlstr);
           DebugLog.logger.log(Level.INFO,"获取数据集成功");
           return rs;
         }
         catch(SQLException e)
         {
           DebugLog.logger.log(Level.WARNING,"获取数据集时出现错误");
           DebugLog.logger.log(Level.WARNING,e.getMessage());
           try{
           conn.rollback();
           }
           catch(SQLException i)
       {
           DebugLog.logger.log(Level.WARNING,"回滚数据集时出现错误");
           DebugLog.logger.log(Level.WARNING,i.getMessage());
       }
           return null;
         }
         catch(Exception cnfe){
         DebugLog.logger.log(Level.WARNING,"获取数据集时出现错误");
         DebugLog.logger.log(Level.WARNING,cnfe.getMessage());
         return null;
         }finally{
         try{
         if(rs != null){
         rs.close();
         }
         if(stmt != null){
         stmt.close();
         }
         }catch(SQLException j){
         DebugLog.logger.log(Level.WARNING,"关闭数据集时出现错误");
         DebugLog.logger.log(Level.WARNING,j.getMessage());
         }     
         }
      }
    但是这段代码的问题是,每次取这段代码执行SQL后返回的记录集,就会抛出一个信息为null的异常,我猜想是上面这个函数没返回任何记录集,rs是null的?
    实在不知道什么原因,求高人指教,是什么原因?应该如何修改?谢谢了,我分不多,实在抱歉
      

  5.   

    to zl8108304732() 我现在做的不是web程序哈,是在UNIX上后台运行的一个进程,现在做的项目是电信的一个新业务,这个进程需要在后台不停的处理数据,本来想用C来写的,因为我们公司之前的都是用C来实现,但是不知道怎么用C连接SQLSERVER,之前公司的都是连的oracle,所以改用java了,而且java操作数据库也比c简单的多,这个程序对性能也没太高的要求
    不过还是谢谢你to XinZi(新子),谢谢你哈,恩,你的第一种方式通过上面的代码看出,是不行的,因为要返回rs
    现在这个新业务除了因为有些statement用完没有关闭,运行时间长了会出现ora-01000: maximum open cursors exceeded.,业务处理上已经测试没什么问题了,所以不想大改了,否则还得重新测试?电信的这个新业务马上就要推出去了
    我试下你的第三种方式
      

  6.   

    有没有更好更简单的解决方法?比如connection的某个方法可以关闭该connection的所有创建的statement?
      

  7.   

    调用Connection.close()关闭所有Statment和ResultSet,调用Statment.close()关闭所有ResultSet。
    "resultset.close();"后面的“ resultset=null;”是多于的。"
    Statment变量用完得关闭,特别是变量被多次赋值(stmt=conn.createStatement()),就会很容易导致ora-100之类的错误。查看JDBC源码很容易理解。
      

  8.   

    多谢hanjin26() ,难道只能通过Connection.close()来关闭所有的Statment和ResultSet了吗?
    没有只是关闭所有的Statment和ResultSet而不需要关闭Connection的方法哈?
    我前面已经说过,我的程序需要不停的操作数据库,是一个电信项目,所以connection要一直保持,不去关闭它,不然开销太大
      

  9.   

    不是不是,我这个程序没有那么多的数据库,就两个数据库,所以我的程序里只有两个连接,一个连接连一个数据库,没有你说的那么多的连接
    只是这两个连接一直保持,不断进行数据处理,而且因为我主程序对每个数据库只进行一次连接,连接后进行数据处理,数据处理放在一个无线循环中,只是不停的执行SQL语句,不在进行数据库连接,所以整个进行一直保持的只有两个连接,哪有几千几万啊,进程异常退出才会关闭这两个连接的
      

  10.   

    rs用完就关,
             没有那种关所有rs和sm的方法.
               既然在循环里面就3,4句话都懒得写...
      

  11.   

    不是3,4句,我的程序因为操作数据库比较多,得有10几句哈而且有的时候还不好关闭,比如
                     rs3 = this.Conn1.executeSql(sql3);
    try{
    while(rs3.next()){
    ........
    rs4 = this.Conn1.executeSql(sql4);try{
    while(rs4.next()){.........
      }catch(){
      
      }
     }
     }catch(){ 
      
     }
    请问上面这段怎么关闭statment和resultset?其中this.Conn1是和一个数据库的连接,对这个数据库嵌套做了操作,如果里层的while(rs4.next())关闭了statment和resultset,会不会影响外层的while(rs3.next())而使外层的循环不能在继续了
      

  12.   

    建议自己实现一个Connection接口的类,然后里面封装一个Connection对象,然后自己实现一下CreateStatement方法,除了创建Statement外,把所有的Statement放在一个列表里面,增加一个关闭所有Statement方法,把列表里面的所有的Statement全部关闭掉。
      

  13.   

    既然return rs,返回了结果集,就不能在finally中把rs.close()掉,return之前会执行finally里的内容rs用完就关,如果是嫌麻烦就自己写个函数一起关,如果是因为有循环嵌套不能关的,就封闭到集合中再循环谁调用了executeSql方法就由谁关
      

  14.   

    用连接池,apache 的,c3p0 的都不错。你也可以试试这个是我些的
    http://www.jspx.net/down/lib/jspxdbs-1.0.jar    <bean id="jspxDataSource" class="com.jspx.datasource.JspxDataSource" destroy="close">
            <string name="driverClass">${driverClassName}</string>
            <string name="jdbcUrl"><![CDATA[${jdbcUrl}]]></string>
            <string name="user">${username}</string>
            <string name="password">${password}</string>
        </bean>当你关闭的时候它不会关闭,当没有使用连接的时候会自动关闭连接。
    setMaxPoolSize 设置最大连接数。
    setMaxConnectionTime 最大连接等待时间,单位毫秒,超过这个时间就关闭。
      

  15.   

    世纪书缘时隔两年多,《Java编程思想(第4版)》的中文版又要和广大Java程序员和爱好者们见面了。这是Java语言本身不断发展和完善的必然要求,也是本书作者Bruce Eckel孜孜不倦的创作激情和灵感所结出的硕果。《Java编程思想(第4版)》以Java最新的版本JDK5.0为基础,在第3版的基础上,添加了最新的语言特性,并且对第3版的结构进行了调整,使得所有章节的安排更加遵照循序渐进的特点,同时每一章的内容在分量上也都更加均衡,这使读者能够更加容易地阅读本书并充分了解每章所讲述的内容。在这里我们再次向Bruce Eckel致敬,他不但向我们展示了什么样的书籍才是经典书籍,而且还展示了经典书籍怎样才能精益求精,长盛不衰。Java已经成为了编程语言的骄子。我们可以看到,越来越多的大学在教授数据结构、程序设计和算法分析等课程时,选择以Java语言为载体。这说明Java语言已经是人们构建软件系统时主要使用的一种编程语言。但是,掌握好Java语言并不是一件可以轻松完成的任务,如何真正掌握Java语言,从而编写出健壮的、高效的以及灵活的程序是Java程序员们面临的重大挑战。《Java编程思想(第4版)》就是一本能够让Java程序员轻松面对这一挑战,并最终取得胜利的经典书籍。本书深入浅出、循序渐进地把我们领入Java的世界,让我们在不知不觉中就学会了用Java的思想去考虑问题、解决问题。本书不仅适合Java的初学者,更适合于有经验的Java程序员,这正是本书的魅力所在。但是,书中并没有涵盖Java所有的类、接口和方法,因此,如果你希望将它当作Java的字典来使用,那么显然就要失望了。我们在翻译本书的过程中力求忠于原著,为了保持连贯性,对原书第3版中仍然保持不变的部分,我们对译文除了个别地方之外,也没做修改。对于本书中出现的大量的专业术语尽量遵循标准的译法,并在有可能引起歧义之处注有英文原文,以方便读者对照与理解。全书由陈昊鹏翻译,郭嘉也参与了部分翻译工作。由于水平有限,书中出现错误与不妥之处在所难免,恳请读者批评指正。www.sjsy.net转载
      

  16.   

    wang_wei2007() 如果是因为有循环嵌套不能关的,就封闭到集合中再循环什么意思?能具体说说吗?比如
     rs3 = this.Conn1.executeSql(sql3);
    try{
    while(rs3.next()){
    ........
    rs4 = this.Conn1.executeSql(sql4);try{
    while(rs4.next()){.........
      }catch(){
      
      }
     }
     }catch(){ 
      
     }
    这样一段代码的关闭代码应该怎么写?
      

  17.   

    疑问:
    一个connection能带好多有效的resultset和statement吗?我怎么觉得只能1拖1 的?
      

  18.   

    to:jihanzhong(逍遥)一个connection能带好多有效的resultset和statement吗?
    应该可以,我程序里一个connection就带了好多resultset和statement,但是都能返回正确的结果
      

  19.   

    其实我也一直在找楼主说的解决方案
    并且想通过代理接口的方式实现
    后来发现不妥,只好放弃了,
    因为Connection生成的Statement和ResultSet始终不释放,
    而是到最后才释放,可能会达到数据库联接的最大游标数而导致错误
    例如:
    try{
      rs1 = stmt.executeSql(sql1);
      while(rs1.next()){...}  rs2 = stmt.executeSql(sql2);
      while(rs2.next()){...}
      ...  rs100 = stmt.executeSql(sql4);
      while(rs100.next()){...} }catch(Exception){}
     finally{
        closeDBSourse(rs1);//1
        closeDBSourse(rs2);//2
        ...
        closeDBSourse(rs100);//100
        //1-100可能封装在函数101中    freeDBSourse(stmt);//101
     }
    可能在执行过程中会占用多个数据库游标,存在隐患。
    目前我采用的实现方式如下,虽然比较繁琐,但很安全:
    try{
      rs1 = stmt.executeSql(sql1);
      while(rs1.next()){...}
      closeDBSourse(rs1);  rs2 = stmt.executeSql(sql2);
      while(rs2.next()){...}
      closeDBSourse(rs2);
      ...  rs100 = stmt.executeSql(sql4);
      while(rs100.next()){...}
      closeDBSourse(rs100); }catch(Exception){}
     finally{
        freeDBSourse(stmt);
     }
      

  20.   

    public ResultSet executeSql(String sqlstr){}我认为像这样的设计就很不合理,至少返回的是一个封装后的数据(如:List),而不是直接返回一个 ResultSet,而且 finally 是先执行的(在其中关闭了 ResultSet),这个再返回就得不到结果集了。这个方法应该改为:public List<xxxx> executeSql(String sqlstr){}这样就可以在里面直接关掉了。
      

  21.   

    还是在哪儿用到STATEMENT,RESULTSET就在哪儿关闭比较好吧
      

  22.   

    这个方法应该改为:
    public List<xxxx> executeSql(String sqlstr){}
    =============================================
    怎么实现这个方法呢?
    ResultSet中返回的各字段属性不知道呀
    是不是每个查询都要写一个这种方法,这可能要累死人
      

  23.   

    其实我也一直在找楼主说的解决方案 
    并且想通过代理接口的方式实现 
    后来发现不妥,只好放弃了, 
    因为Connection生成的Statement和ResultSet始终不释放, 
    而是到最后才释放,可能会达到数据库联接的最大游标数而导致错误 
    例如: 
    try{ 
        rs1   =   stmt.executeSql(sql1); 
        while(rs1.next()){...}     rs2   =   stmt.executeSql(sql2); 
        while(rs2.next()){...} 
        ...     rs100   =   stmt.executeSql(sql4); 
        while(rs100.next()){...}   }catch(Exception){} 
      finally{ 
            closeDBSourse(rs1);//1 
            closeDBSourse(rs2);//2 
            ... 
            closeDBSourse(rs100);//100 
            //1-100可能封装在函数101中         freeDBSourse(stmt);//101 
      } 
    可能在执行过程中会占用多个数据库游标,存在隐患。 
    目前我采用的实现方式如下,虽然比较繁琐,但很安全: 
    try{ 
        rs1   =   stmt.executeSql(sql1); 
        while(rs1.next()){...} 
        closeDBSourse(rs1);     rs2   =   stmt.executeSql(sql2); 
        while(rs2.next()){...} 
        closeDBSourse(rs2); 
        ...     rs100   =   stmt.executeSql(sql4); 
        while(rs100.next()){...} 
        closeDBSourse(rs100);   }catch(Exception){} 
      finally{ 
            freeDBSourse(stmt); 
      }
      

  24.   

    直接返回ResultSet是不推荐的
    应该根据自己的需求封装自己需要的数据类型,作为返回类型
    这样就可以在返回之前关闭ResultSet
      

  25.   

    别返回ResultSet,这样调用方和你这个方法的耦合程度就太高了而且,你在你的方法里没法释放资源啊。