2009-06-01 12 views
21

Tan pronto como mi código llegue a mi lazo while(rs.next()), produce la excepción ResultSet está cerrada. ¿Qué causa esta excepción y cómo puedo corregirla?¿Cómo puedo evitar que ResultSet sea una excepción cerrada en Java?

EDIT: noto en mi código que estoy anidación while(rs.next()) bucle con otro (rs2.next()), ambos conjuntos de resultados procedentes de la misma base de datos, es esto un problema?

+5

Agregue un listado de su código. – JeeBee

Respuesta

39

Parece que ejecutó otra sentencia en la misma conexión antes de recorrer el conjunto de resultados de la primera instrucción. Si anida el procesamiento de dos conjuntos de resultados de la misma base de datos, está haciendo algo mal. La combinación de esos conjuntos debe hacerse en el lado de la base de datos.

+0

sí, eso es lo que hice, gracias por la explicación. –

+4

Esto no es cierto para todos los controladores y RDBMS. –

+0

sqlserver.jar no puede hacerlo anidando, pero jtds.jar puede hacerlo. –

6

La excepción indica que su resultado está cerrado. Debería examinar su código y buscar toda la ubicación donde emite una llamada ResultSet.close(). También busque Statement.close() y Connection.close(). Con seguridad, uno de ellos recibe una llamada antes de llamar al rs.next().

4

Es posible que haya cerrado o bien el Connection o Statement que hizo el ResultSet, lo que llevaría a la ResultSet cerrándose así.

9

Además, solo puede tener un conjunto de resultados abierto desde cada extracto. Por lo tanto, si está iterando a través de dos conjuntos de resultados al mismo tiempo, asegúrese de que se ejecuten en declaraciones diferentes. Abrir un segundo conjunto de resultados en una declaración cerrará implícitamente la primera. http://java.sun.com/javase/6/docs/api/java/sql/Statement.html

4

llamada JDBC correcto debería ser algo como:

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()); 
} 

puede cerrar la conexión (o declaración) sólo después de obtener resultado de conjunto de resultados. La forma más segura es hacerlo en el bloque finally. Sin embargo, close() también podría throe SqlException, de ahí el otro bloque try-catch.

+1

Tengo que amar a ese try/catch anidado. A veces realmente aborrezco JDBC. Hincha este ejemplo, pero debería cerrar el conjunto de resultados y la declaración también. ¡Lo llamaste una llamada JDBC adecuada! – banjollity

+0

necesita una verificación si rs/stmt/conn no es nulo ... –

+0

@DanielMagnusson Tienes razón. He arreglado la respuesta. – Slartibartfast

17

Esto podría deberse a varias razones, incluido el controlador que está utilizando.

a) Algunos controladores no permiten declaraciones anidadas. Dependiendo de si su controlador admite JDBC 3.0, debe verificar el tercer parámetro al crear el objeto Statement. Por ejemplo, tuve el mismo problema con el controlador de JayBird para Firebird, pero el código funcionaba bien con el controlador de postgres. Luego agregué el tercer parámetro a la llamada al método createStatement y lo configuré en ResultSet.HOLD_CURSORS_OVER_COMMIT, y el código también funcionó bien para 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) Puede haber un error en su código. Recuerde que no puede reutilizar el objeto Statement, una vez que vuelva a ejecutar una consulta en el mismo objeto de declaración, se cerrarán todos los resultados abiertos asociados con la declaración. Asegúrese de no cerrar la declaración.

+0

Estaba teniendo el mismo problema con los controladores Firebird JDBC. Puedo verificar que el 'ResultSet.HOLD_CURSORS_OVER_COMMIT' está funcionando. –

+0

¡Los mismos problemas en los controladores de DB2 también se resuelven con esta bandera! – bobbel

2

Compruebe si ha declarado el método donde se está ejecutando este código como static. Si es static, puede haber algún otro hilo reiniciando el ResultSet.

1

Recibí el mismo error, todo fue correcto, solo estaba usando el mismo objeto de interfaz de declaración para ejecutar y actualizar la base de datos. Después de separar, es decir, utilizando diferentes objetos de la interfaz de declaración para actualizar y ejecutar la consulta, resolví este error. es decirDeshazte de esto. No uses el mismo objeto de declaración para actualizar y ejecutar la consulta.

Cuestiones relacionadas