usuario - ¿Cómo puedo evitar que ResultSet sea una excepción cerrada en Java?
sqlexception c# (9)
Tan pronto como mi código llegue a mi while(rs.next())
, produce el ResultSet
es una excepción cerrada. ¿Qué causa esta excepción y cómo puedo corregirla?
EDIT: noté en mi código que estoy anidando while(rs.next())
loop con otro (rs2.next())
, ambos conjuntos de resultados provenientes de la misma base de datos, ¿es esto un problema?
Además, solo puede tener un conjunto de resultados abierto desde cada declaración. 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
Compruebe si ha declarado static
el método donde este código se está ejecutando. Si es static
, puede haber algún otro subproceso que restablezca el ResultSet
.
Es posible que haya cerrado la Connection
o la Statement
que hizo el ResultSet
, lo que llevaría a que el ResultSet
se cerrara también.
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 tu 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.
La excepción establece que su resultado está cerrado. Debería examinar su código y buscar todas las ubicaciones donde emite una llamada a ResultSet.close()
. Busque también Statement.close()
y Connection.close()
. Con seguridad, uno de ellos recibe una llamada antes de llamar a rs.next()
.
La llamada a jdbc adecuada debería verse más o menos así:
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 instrucción) solo después de obtener el resultado del conjunto de resultados. La forma más segura es hacerlo en el bloque final. Sin embargo close()
también podría throe SqlException
, de ahí el otro bloque try-catch
.
Obtuve el mismo error, todo fue correcto, solo que estaba usando el mismo objeto de interfaz de declaración para ejecutar y actualizar la base de datos. Después de separar, es decir, usar diferentes objetos de la interfaz de declaración para actualizar y ejecutar la consulta, resolví este error. es decir, deshazte de esto, no uses el mismo objeto de declaración tanto para actualizar como para ejecutar la consulta.
Parece que ejecutó otra sentencia en la misma conexión antes de recorrer el conjunto de resultados de la primera declaració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.
asegúrese de haber cerrado todas sus declaraciones y resultados antes de ejecutar rs.next. Finaly garantiza esto
public boolean flowExists( Integer idStatusPrevious, Integer idStatus, Connection connection ) {
LogUtil.logRequestMethod();
PreparedStatement ps = null;
ResultSet rs = null;
try {
ps = connection.prepareStatement( Constants.SCRIPT_SELECT_FIND_FLOW_STATUS_BY_STATUS );
ps.setInt( 1, idStatusPrevious );
ps.setInt( 2, idStatus );
rs = ps.executeQuery();
Long count = 0L;
if ( rs != null ) {
while ( rs.next() ) {
count = rs.getLong( 1 );
break;
}
}
LogUtil.logSuccessMethod();
return count > 0L;
} catch ( Exception e ) {
String errorMsg = String
.format( Constants.ERROR_FINALIZED_METHOD, ( e.getMessage() != null ? e.getMessage() : "" ) );
LogUtil.logError( errorMsg, e );
throw new FatalException( errorMsg );
} finally {
rs.close();
ps.close();
}