2010-03-02 26 views
21

Al usar un PreparedStatement en JDBC, ¿debo cerrar primero el PreparedStatement o el Connection primero? Acabo de ver un ejemplo de código en el que el Connection se cierra primero, pero me parece más lógico cerrar el PreparedStatement primero.¿Qué debo cerrar primero, PreparedStatement o Connection?

¿Existe una forma estándar y aceptada para hacer esto? ¿Importa? ¿Cerrar el Connection también causa que el PreparedStatement se cierre, ya que el PreparedStatement está directamente relacionado con el objeto Connection?

+1

¿Dónde lo viste? – BalusC

+0

Aunque según la especificación, la declaración debe cerrarse cuando se cierra la conexión, se ha visto que los controladores JDBC tienen problemas con esto, por lo que se considera una buena práctica cerrar explícitamente la instrucción (y el conjunto de resultados). – Yishai

+0

Cierre las cosas en el orden inverso al que las abrió. Todas las cosas. – EJP

Respuesta

36

La declaración. Yo esperaría que cierres (en orden)

  1. el conjunto de resultados
  2. la declaración
  3. la conexión

(y comprobar si hay valores nulos en el camino!)

es decir, cerrar en orden inverso a la secuencia de apertura.

Si utiliza Spring JdbcTemplate (o similar), eso se ocupará de esto por usted. Alternativamente, puede usar Apache Commons DbUtils y DbUtils.close() o DbUtils.closeQuietly().

+1

De hecho. Algunos controladores JDBC lanzarán una excepción al cerrar un conjunto de resultados o una declaración después de que se cierre la conexión. – Yishai

+11

Eso es correcto. Hasta el punto: cierre los * recursos * en ** orden inverso ** a medida que los adquirió. – BalusC

7

Los siguientes procedimientos se debe hacer (en orden)

  • El ResultSet
  • El PreparedStatement
  • El Connection.

Además, es aconsejable cerrar todos los objetos relacionados con JDBC en el finally para garantizar el cierre.

//Do the following when dealing with JDBC. This is how I've implemented my JDBC transactions through DAO.... 

Connection conn = null; 
PreparedStatement ps = null; 
ResultSet rs = null; 

try { 
    conn = .... 
    ps = conn.prepareStatement(...); 

    //Populate PreparedStatement 
    rs = ps.executeQuery(); 

} catch (/*All relevant exceptions such as SQLException*/Exception e) { 
    logger.error("Damn, stupid exception: " , e); 
} finally { 
if (rs != null) { 
      try { 
       rs.close(); 
       rs = null; 
      } catch (SQLException e) { 
       logger.error(e.getMessage(), e.fillInStackTrace()); 
      } 
     } 

     if (ps != null) { 
      try { 
       ps.close(); 
       ps = null; 
      } catch (SQLException e) { 
       logger.error(e.getMessage(), e.fillInStackTrace()); 
      } 
     } 

     try { 
      if (conn!= null && !conn.isClosed()){ 
       if (!conn.getAutoCommit()) { 
        conn.commit(); 
        conn.setAutoCommit(true); 
       } 
       conn.close(); 
       conn= null; 
      } 
     } catch (SQLException sqle) { 
      logger.error(sqle.getMessage(), sqle.fillInStackTrace()); 
     } 
} 

Se puede ver que he comprobado si mis objetos son nulos y para la conexión, compruebe primera si no se autocommited la conexión. Muchas personas no lo comprueban y se dan cuenta de que la transacción no se ha comprometido con DB.

+5

Todo eso, finalmente, el compendio debe condensarse en un método de utilidad (por ejemplo, 'DBUtils.close (rs, ps, conn);'). Además, el consejo sobre autocommit depende de la situación. A veces, cuando hay una excepción, no quiere comprometerse en absoluto. Además, el esfuerzo de establecer explícitamente la referencia a null casi siempre es innecesario, ya que se eliminará cuando el método finalice, lo que es de esperar muy pronto después de esto, de lo contrario, es probable que el método sea demasiado extenso. – Yishai

+0

@Yishai - gracias, me preguntaba sobre eso. – froadie

+0

@Yishai, sí, olvidé mencionar que si hay excepciones y el autocommit está desactivado, puede hacer una reversión ... Gracias por mostrar esto. –

Cuestiones relacionadas