2010-01-23 10 views
6

Tengo una aplicación de Java que abre una conexión a una base de datos al principio y la cierra al final. Sin embargo, el programa no siempre termina, porque se lanza una excepción o lo estoy depurando y deteniéndolo a la mitad.¿Problema con no cerrar la conexión de db durante la depuración?

¿Causará esto que las conexiones abiertas se acumulen y ralenticen la base de datos o se limpiarán automáticamente?

Respuesta

8

una conexión de base es propiedad y está gestionado por la base de datos, la clase sólo da usted tiene acceso a ese recurso de base de datos. Si no cierra la conexión, la clase Java puede ser basura, pero es posible que la base de datos no advierta que la conexión ya no está en uso, lo que puede ocasionar desperdicio de recursos de la base de datos (hasta un tiempo de espera en el lado de la base de datos)) o incluso fugas.

Así que, cuando haya terminado con el uso del Connection, usted debe estar seguro de para cerrar explícitamente llamando a su método close(). Esto permitirá que el recolector de basura recupere memoria tan pronto como sea posible y, más importante, libera cualquier otro recurso de base de datos (cursores, identificadores, etc.) a los que la conexión se pueda retener.

La forma tradicional de hacer esto en Java es cerrar los ResultSet, Statement y Connection (en ese orden) en un bloque finally cuando haya terminado con ellos y el patrón de seguridad se ve así:

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 bloque finally puede ser mejorado ligeramente en (para evitar el cheque nulo):

} 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 terminan usando una clase de ayuda a cerrar los objetos en los métodos de ayuda nulos de fallos y el bloque finally se convierte en algo así:

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

Y, en realidad, la Apache Commons DbUtils tiene una clase DbUtils que está haciendo precisamente lo que no hay necesidad de escribe lo tuyo.

En su caso, esto resolverá el problema de la excepción, pero no la depuración (y desperdiciará los recursos de la base de datos hasta que ocurra el tiempo de espera en el lado de la base de datos). Entonces 1. no depure su código usando una base de datos de producción 2. intente ejecutar su sesión de depuración hasta el final.

+1

Los chicos de Sun estaban INSANE cuando decidieron no tener destructores. Era mucho más fácil cerrar cualquier recurso abierto en destructores como en C++. Ahora, solo miren toda esa basura que necesitamos escribir solo para una consulta de base de datos pequeña ... Se debería haber hecho en 3 líneas de código: conectarse a db, ejecutar consulta, obtener resultado. –

0

No.

Si su programa continúa y sus conexiones están activas, entonces el BD simplemente rechazó su oración.

Si algo sucedió con su conexión (por ejemplo, un tiempo de espera) entonces el BD fue quien cerró esa conexión y no está consumiendo recursos.

Si liberó su conexión, y se llamó al recolector de basura (puede pasar un tiempo), la conexión se cerrará antes de ser liberada.

Si su programa finalizó sin cerrar su conexión, entonces todo el proceso (del sistema operativo) liberará sus recursos nativos, y entre ellos, el recurso nativo que se conectó al BD (probable un socket de red). El BD recibirá la conexión abortada/cerrada y liberará su conexión.

Lo único que podría suceder es que una única ejecución se conectaría muchas veces al BD y haría las cosas mal para mantenerlas abiertas, ocupando todas las conexiones disponibles. Pero no es tu caso, creo.

Editar: en BD generales de se hacen mal comportamiento-cliente- -proof

2

Esto es lo que Sun (err ... Oracle?) says:

Se recomienda que los programadores de cierre de forma explícita conexiones y declaraciones que han creado cuando ya no son necesarios.

Un programador que escribe código en el lenguaje de programación Java y no utiliza ningún recurso externo no necesita preocuparse por la gestión de la memoria. El recolector de basura elimina objetos automáticamente cuando ya no se usan y libera la memoria que estaban usando. Cuando la memoria se está agotando, reciclará los objetos descartados, haciendo que la memoria que ocupan actualmente esté disponible para su reutilización rápida.

Sin embargo, si una aplicación utiliza recursos externos, como lo hace cuando accede a un DBMS con la API JDBC, el recolector de elementos no utilizados no tiene forma de conocer el estado de esos recursos. Todavía reciclará los objetos descartados, pero si hay mucha memoria libre en el montón de Java, puede que la basura se acumule con poca frecuencia, a pesar de que la cantidad (pequeña) de basura de Java mantiene abiertas grandes cantidades de costosos recursos de la base de datos. Por lo tanto, se recomienda que los programadores cierren explícitamente todas las conexiones (con el método Connection.close) y las declaraciones (con el método Statement.close) tan pronto como ya no las necesiten, liberando así los recursos de DBMS lo antes posible. Esto se aplica especialmente a las aplicaciones que están destinadas a trabajar con diferentes DBMS debido a las variaciones de un DBMS a otro.

Pondría el acceso a la base de datos en un bloque try y me aseguraré de cerrar todas las declaraciones y conexiones en un bloque finally.

2

Su servidor db tendrá una configuración de tiempo de espera. Cerrará la conexión y revertirá cualquier transacción no confirmada. Esto ha estado sucediendo durante décadas en cualquier producto db capaz de producción.

Si desea hacerlo utilizar correctamente un try {..your código ..} {} conexiones ..close .. finalmente

+0

Además, la mayoría de los protocolos DB hacen ping al otro lado para ver si está activo. –

Cuestiones relacionadas