Cerrar conexiones de bases de datos en Java
Me estoy confundiendo un poco. Estaba leyendo lo siguiente de Java Database Connectivity :
Connection conn = DriverManager.getConnection(
"jdbc:somejdbcvendor:other data needed by some jdbc vendor",
"myLogin",
"myPassword" );
Statement stmt = conn.createStatement();
try {
stmt.executeUpdate( "INSERT INTO MyTable( name ) VALUES ( 'my name' ) " );
} finally {
// It's important to close the statement when you are done with it
stmt.close();
}
¿ No es necesario cerrar la conn
conexión? ¿Qué sucede realmente si conn.close() no ocurre?
Tengo una aplicación web privada que mantengo y que actualmente no cierra ninguno de los formularios, pero ¿el importante es realmente el stmt
uno, el conn
uno o ambos?
El sitio sigue cayendo de forma intermitente, pero el servidor sigue diciendo que es un problema de conexión a la base de datos. Mi sospecha es que no se está cerrando, pero no sé cuál cerrar, si es que hay alguno.
Cuando haya terminado de usar su Connection
, deberá cerrarlo explícitamente llamando a su close()
método para liberar cualquier otro recurso de la base de datos (cursores, identificadores, etc.) que la conexión pueda estar reteniendo.
En realidad, el patrón seguro en Java es cerrar ResultSet
, Statement
y Connection
(en ese orden) en un finally
bloque cuando haya terminado con ellos. Algo como esto:
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
// Do stuff
...
} catch (SQLException ex) {
// Exception handling stuff
...
} finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) { /* Ignored */}
}
if (ps != null) {
try {
ps.close();
} catch (SQLException e) { /* Ignored */}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) { /* Ignored */}
}
}
El finally
bloque se puede mejorar ligeramente (para evitar la verificación nula):
} finally {
try { rs.close(); } catch (Exception e) { /* Ignored */ }
try { ps.close(); } catch (Exception e) { /* Ignored */ }
try { conn.close(); } catch (Exception e) { /* Ignored */ }
}
Pero, aún así, esto es extremadamente detallado por lo que generalmente terminas usando una clase auxiliar para cerrar los objetos en métodos auxiliares seguros para nulos y el finally
bloque se convierte en algo como esto:
} finally {
DbUtils.closeQuietly(rs);
DbUtils.closeQuietly(ps);
DbUtils.closeQuietly(conn);
}
Y, de hecho, Apache Commons DbUtils tiene una DbUtils
clase que hace precisamente eso, por lo que no es necesario escribir la tuya propia.
Siempre es mejor cerrar los objetos de base de datos/recursos después de su uso. Es mejor cerrar los objetos de conexión, conjunto de resultados y declaración en el finally
bloque.
Hasta Java 7, todos estos recursos debían cerrarse mediante un finally
bloque. Si está utilizando Java 7, para cerrar los recursos, puede hacer lo siguiente.
try(Connection con = getConnection(url, username, password, "org.postgresql.Driver");
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(sql);
) {
// Statements
}
catch(....){}
Ahora, los con
objetos stmt
y rs
pasan a formar parte del bloque try y Java cierra automáticamente estos recursos después de su uso.
En realidad, es mejor si usa un bloque de prueba con recursos y Java cerrará todas las conexiones cuando salga del bloque de prueba.
Debes hacer esto con cualquier objeto que implemente AutoClosable.
try (Connection connection = getDatabaseConnection(); Statement statement = connection.createStatement()) {
String sqlToExecute = "SELECT * FROM persons";
try (ResultSet resultSet = statement.execute(sqlToExecute)) {
if (resultSet.next()) {
System.out.println(resultSet.getString("name");
}
}
} catch (SQLException e) {
System.out.println("Failed to select persons.");
}
La llamada a getDatabaseConnection acaba de inventarse. Reemplácelo con una llamada que le proporcione una conexión JDBC SQL o una conexión desde un grupo.