2009-06-01 21 views
21

私のコードが私のwhile(rs.next())ループに到達するとすぐに、ResultSetが閉じた例外を生成します。この例外の原因は何ですか?どのように修正できますか?JavaでResultSetがクローズされた例外を回避するにはどうすればよいですか?

EDIT:私は自分のコードに気づく、私は別の(rs2.next())while(rs.next())ループを入れ子にしています、両方の結果セットが同じDBから来て、これは問題でしょうか?

+5

コードの一覧を追加します。 – JeeBee

答えて

39

同じ接続で別のステートメントを実行した後、最初のステートメントから結果セットをトラバースするように聞こえるように聞こえます。同じデータベースの2つの結果セットの処理を入れ子にしている場合は、何か問題があります。これらのセットの組み合わせはデータベース側で行う必要があります。

+0

私は何をしたのですか、説明に感謝します。 –

+4

これは、すべてのドライバとRDBMSでは当てはまりません。 –

+0

sqlserver.jarは入れ子にすることはできませんが、jtds.jarはそれを行うことができます。 –

6

結果には例外があります。コードを調べて、ResultSet.close()コールを発行するすべての場所を探す必要があります。 Statement.close()Connection.close()も探してください。確かに、rs.next()が呼び出される前に、そのうちの1つが呼び出されます。

4

あなたは閉じられている可能性のいずれかResultSetにつながるResultSetを作っConnectionまたはStatementは、同様に閉鎖されています。

9

また、各文から1つの結果セットしか開くことができません。したがって、同時に2つの結果セットを反復処理する場合は、それらが異なるステートメントで実行されていることを確認してください。 1つのステートメントで2つ目の結果セットを開くと、暗黙的に最初のステートメントが閉じられます。 http://java.sun.com/javase/6/docs/api/java/sql/Statement.html

4

適切なJDBC呼び出しのようなものになります。

try { 
    Connection conn; 
    Statement stmt; 
    ResultSet rs; 

    try { 
     conn = DriverManager.getConnection(myUrl,"",""); 
     stmt = conn.createStatement(); 
     rs = stmt.executeQuery(myQuery); 

     while (rs.next()) { 
      // process results 
     } 

    } catch (SqlException e) { 
     System.err.println("Got an exception! "); 
     System.err.println(e.getMessage()); 
    } finally { 
     // you should release your resources here 
     if (rs != null) { 
      rs.close(); 
     } 

     if (stmt != null) { 
      stmt.close(); 
     } 

     if (conn != null) { 
      conn.close(); 
     } 
    } 
} catch (SqlException e) { 
    System.err.println("Got an exception! "); 
    System.err.println(e.getMessage()); 
} 

を、あなたは結果セットから結果を取得した後にのみ接続(またはステートメント)を閉じることができます。最も安全な方法はfinallyブロックで行うことです。しかし、close()もまたSqlExceptionを突き抜けた可能性があります。したがって、もう1つのtry-catchブロックです。

+1

ネストされたtry/catchが大好きです。時には私は本当にJDBCを嫌う。この例は膨らみますが、実際には結果セットとステートメントも閉じてください。あなたはそれを適切なJDBC呼び出しと呼びました! – banjollity

+0

は、rs/stmt/connがヌルでないかどうかチェックする必要があります。 –

+0

@DanielMagnussonそうです。私は答えを修正しました。 – Slartibartfast

17

これは、使用しているドライバを含む多くの理由によって発生する可能性があります。

a)一部のドライバでは、ネストされた文を使用できません。ドライバがJDBC 3.0をサポートしているかどうかによって、Statementオブジェクトの作成時に3番目のパラメータを確認する必要があります。たとえば、FirebirdのJayBirdドライバと同じ問題がありましたが、コードはpostgresドライバでうまく動作しました。次に、3番目のパラメータをcreateStatementメソッド呼び出しに追加し、ResultSet.HOLD_CURSORS_OVER_COMMITに設定し、コードがFirebirdでも正常に動作するようになりました。

static void testNestedRS() throws SQLException { 

    Connection con =null; 
    try { 
     // GET A CONNECTION 
     con = ConexionDesdeArchivo.obtenerConexion("examen-dest"); 
     String sql1 = "select * from reportes_clasificacion"; 

     Statement st1 = con.createStatement(
       ResultSet.TYPE_SCROLL_INSENSITIVE, 
       ResultSet.CONCUR_READ_ONLY, 
       ResultSet.HOLD_CURSORS_OVER_COMMIT); 
     ResultSet rs1 = null; 

     try { 
      // EXECUTE THE FIRST QRY 
      rs1 = st1.executeQuery(sql1); 

      while (rs1.next()) { 
       // THIS LINE WILL BE PRINTED JUST ONCE ON 
            // SOME DRIVERS UNLESS YOU CREATE THE STATEMENT 
       // WITH 3 PARAMETERS USING 
            // ResultSet.HOLD_CURSORS_OVER_COMMIT 
       System.out.println("ST1 Row #: " + rs1.getRow()); 

       String sql2 = "select * from reportes"; 
       Statement st2 = con.createStatement(
         ResultSet.TYPE_SCROLL_INSENSITIVE, 
         ResultSet.CONCUR_READ_ONLY); 

       // EXECUTE THE SECOND QRY. THIS CLOSES THE FIRST 
       // ResultSet ON SOME DRIVERS WITHOUT USING 
            // ResultSet.HOLD_CURSORS_OVER_COMMIT 

       st2.executeQuery(sql2); 

       st2.close(); 
      } 
     } catch (SQLException e) { 
      e.printStackTrace(); 
     } finally { 
      rs1.close(); 
      st1.close(); 
     } 

    } catch (SQLException e) { 

    } finally { 
     con.close(); 

    } 

} 

b)コードにバグがある可能性があります。 Statementオブジェクトを再利用することはできません。同じステートメントオブジェクトに対してクエリを再実行すると、そのステートメントに関連付けられている開いているすべての結果セットが閉じられます。文を閉じるのではないことを確認してください。

+0

私はFirebird JDBCドライバで同じ問題を抱えていました。私は 'ResultSet.HOLD_CURSORS_OVER_COMMIT'が動作していることを確認できます。 –

+0

DB2ドライバでも同じ問題がこのフラグで解決されます。 – bobbel

2

このコードの実行方法をstaticとして宣言しているかどうかを確認してください。 staticの場合、ResultSetをリセットしている他のスレッドがある可能性があります。

1

私はすべて同じエラーが発生しました。私は同じステートメントのインターフェイスオブジェクトを使用してデータベースを実行していました。 クエリの更新と実行にステートメントインタフェースの異なるオブジェクトを使用して分離した後、このエラーが解決されました。すなわち、クエリの更新と実行の両方に同じステートメントオブジェクトを使用しないでください。

関連する問題