Cerrar conexiones de bases de datos en Java

Resuelto onaclov2000 asked hace 14 años • 8 respuestas

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 connconexió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 stmtuno, el connuno 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.

onaclov2000 avatar Feb 09 '10 05:02 onaclov2000
Aceptado

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, Statementy Connection(en ese orden) en un finallybloque 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 finallybloque 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 finallybloque se convierte en algo como esto:

} finally {
    DbUtils.closeQuietly(rs);
    DbUtils.closeQuietly(ps);
    DbUtils.closeQuietly(conn);
}

Y, de hecho, Apache Commons DbUtils tiene una DbUtilsclase que hace precisamente eso, por lo que no es necesario escribir la tuya propia.

Pascal Thivent avatar Feb 08 '2010 22:02 Pascal Thivent

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 finallybloque.

Hasta Java 7, todos estos recursos debían cerrarse mediante un finallybloque. 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 conobjetos stmty rspasan a formar parte del bloque try y Java cierra automáticamente estos recursos después de su uso.

Yadu Krishnan avatar May 02 '2013 06:05 Yadu Krishnan

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.

Joe avatar Sep 13 '2017 16:09 Joe