zoukankan      html  css  js  c++  java
  • 由多次使用Statement实例引起的Result set already closed异常的解决方案

    在不同版本的Weblogic平台上迁移应用,产生了很严重的JDBC驱动版本不兼容的问题。

    但是归根究底是代码的问题,废话少说,上代码示例。

    [java] view plain copy
     
    1. .....  
    2.   
    3. //以下是问题代码  
    4.   
    5. ResultSet rs=null;  
    6.   
    7. Statement st=null;  
    8.   
    9. rs=st.executeQuery("...");  
    10.   
    11. while(rs.next())  
    12.   
    13. {  
    14.   
    15.     String data=rs.getString("...");  
    16.   
    17.     ...........  
    18.   
    19.     ResultSet innerRS=null;  
    20.   
    21.     innerRS=st.executeQuery(".....");//在ojdbc6.jar的实现中,这行代码会关闭rs对象。  
    22.   
    23.     while(innerRS.next())  
    24.   
    25.     {  
    26.   
    27.          String innerData=innerRS.getString(".....");  
    28.   
    29.          .......  
    30.   
    31.     }  
    32.   
    33. }  
    34.   
    35. ......................  



    以上这段代码在使用jdbc-1.4.jar或者ojdbc14.jar这两个包时是没有问题的,前者是独立的JDBC包,后者是Weblogic9.2使用的包。

    但是,如果使用ojdbc6.jar这个包时,问题就会出现了,异常为SQLException: Result set already closed.

    个人推测,Oracle在jdbc-1.4.jar这个版本的JDBC实现中,并未遵守JDBC规范,因为Java规范中明确说道:

    By default, only one ResultSet object per Statement object can be open at the same time. Therefore, if the reading of oneResultSet object is interleaved with the reading of another, each must have been generated by differentStatement objects. All execution methods in the Statement interface implicitly close a statment's currentResultSet object if an open one exists.

    简单来说,就是如果使用同样的Statement执行两次executeQuery查询,那么之前返回的ResultSet对象都会被关闭。

    而很明显,Oracle在其1.4的实现中并未遵循这个规范,而在6这个版本中又遵循了这个规范,所以会在迁移的时候是这个代码本身的问题暴露出来。

    综上所述

    解决方案一:

    在迁移时,为你的应用指定具体的包,防止驱动不兼容的情况。但是这个方法通常很麻烦,因为会有可能在很隐蔽的地方使你指定的驱动不生效。

    解决方案二:

    修改代码,这个是根本的解决之道,只要保证创建了某个ResultSet实例的Statement实例,在这个ResultSet用完之前,不要再次使用就可以。

    至于具体的代码怎样写,最佳实践的例子有很多,不多赘述,只提供上述问题代码的修正版:

    [java] view plain copy
     
      1. .....  
      2.   
      3. //以下是没有问题的代码  
      4.   
      5. ResultSet rs=null;  
      6.   
      7. Statement st=null;  
      8.   
      9. rs=st.executeQuery("...");  
      10.   
      11. while(rs.next())  
      12.   
      13. {  
      14.   
      15.     String data=rs.getString("...");  
      16.   
      17.     ...........  
      18.   
      19.     ResultSet innerRS=null;  
      20.   
      21.     Statement innerST=conn.createStatement();  
      22.   
      23.     innerRS=innerST.executeQuery(".....");//在ojdbc6.jar的实现中,这行代码会关闭rs对象。  
      24.   
      25.     while(innerRS.next())  
      26.   
      27.     {  
      28.   
      29.          String innerData=innerRS.getString(".....");  
      30.   
      31.          .......  
      32.   
      33.     }  
      34.   
      35. }  
      36.   
      37. ......................                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    转:http://blog.csdn.net/sun9701210/article/details/6867366
  • 相关阅读:
    FFT学习及简单应用(一点点详细)
    Codeforces 1131 (div 2)
    【NOI2012】魔幻棋盘
    【hdu多校联考第二场】Odd Shops
    【Helvetic Coding Contest 2018】B2. Maximum Control (medium)
    解线性同余方程组
    Math teacher's homework
    【NOIP模拟赛】一道挖掉背景的数学题
    逆向基础-模块隐藏之断链
    解决请求筛选模块被配置为拒绝包含的查询字符串过长的请求
  • 原文地址:https://www.cnblogs.com/xijin-wu/p/5546213.html
Copyright © 2011-2022 走看看