2009-08-26 7 views
30

menudo me he encontrado con situaciones como: -Try-catch-finally y luego de nuevo un intento de captura

try{ 
    ... 
    stmts 
    ... 
} 
catch(Exception ex) { 
    ... 
    stmts 
    ... 
} finally { 
    connection.close // throws an exception 
} 

que todavía necesita un try - catch dentro finalmente.

¿Cuál es la mejor práctica para superar esto?

+0

Probablemente descubras que la adquisición de recursos también se produce. (Así que realmente use la respuesta de Seth.) –

Respuesta

23

Escriba una clase SQLUtils que contenga static closeQuietly métodos que capturen y registren dichas excepciones, luego utilícelas según corresponda.

que va a terminar con algo que dice así:

public class SQLUtils 
{ 
    private static Log log = LogFactory.getLog(SQLUtils.class); 

    public static void closeQuietly(Connection connection) 
    { 
    try 
    { 
     if (connection != null) 
     { 
     connection.close(); 
     } 
    } 
    catch (SQLExcetpion e) 
    { 
     log.error("An error occurred closing connection.", e); 
    } 
    } 

    public static void closeQuietly(Statement statement) 
    { 
    try 
    { 
     if (statement!= null) 
     { 
     statement.close(); 
     } 
    } 
    catch (SQLExcetpion e) 
    { 
     log.error("An error occurred closing statement.", e); 
    } 
    } 

    public static void closeQuietly(ResultSet resultSet) 
    { 
    try 
    { 
     if (resultSet!= null) 
     { 
     resultSet.close(); 
     } 
    } 
    catch (SQLExcetpion e) 
    { 
     log.error("An error occurred closing result set.", e); 
    } 
    } 
} 

Y su código de cliente será algo como:

Connection connection = null; 
Statement statement = null; 
ResultSet resultSet = null; 
try 
{ 
    connection = getConnection(); 
    statement = connection.prepareStatement(...); 
    resultSet = statement.executeQuery(); 

    ... 
} 
finally 
{ 
    SQLUtils.closeQuietly(resultSet); 
    SQLUtils.closeQuietly(statment); 
    SQLUtils.closeQuietly(connection); 
} 
+8

Esta es mi elección también en el pasado, pero he encontrado estos días que hay clases, como apache commons DBUtil, que hacen esto por usted. –

+0

parece una buena opción :) Gracias – Ajay

10

por lo general lo hice de esta manera:

try { 
    try { 
     .. 
     stmts 
     ... 
    } 
    finally { 
     connection.close(): 
    } 
} catch (Exception ex) { 
    .. 
    stmts 
    ..  
} 

por lo general sólo se utiliza esto cuando no estaba usando una biblioteca que se hizo cargo de esta instalación de cañerías para mí.

Como Imagist señala, esto no es técnicamente el mismo que finalmente se ejecutará antes de la captura, pero creo que resuelve el problema que estabas tratando de resolver.

+0

Eso no es técnicamente lo mismo, pero dependiendo de la situación, podría hacer lo que Ajay quiere. – Imagist

+0

@Imagist: Buen punto. Actualizaré mi respuesta. Gracias. – seth

+0

Por supuesto, puede abstraer eso con el modismo Execute Around. –

1

No dude en uso un intento más ... atrapa el interior finalmente

-1

sólo recuerda .. finalmente siempre consigue ejecutar ya sea con o intento de captura ..

+0

¿Su punto es? –

+0

no obtuvo su punto – Ajay

0

En general, usted no quiere hacer nada más que ingrese una excepción que se produce cuando se cierra un recurso, por lo que realmente debe ir en su propio try/catch. Sin embargo, este es un código genérico que sucederá a menudo, por lo que Do not Repeat Yourself, y ponga el cierre en un método estático (como sugiere Nick Holt) de esa manera no tendrá los dos elementos try/catch en el mismo método, haciendo que el código sea más fácil de leer y seguir.

+0

No estoy seguro de estar de acuerdo con eso. En mi opinión, una falla al cerrar un recurso representa un problema más grave que una excepción típica que ocurriría durante el uso. Uno debe esforzarse por mantener la excepción interna (más fácil en vb.net que C#) pero lanzar una "más grave". – supercat

+0

Si está leyendo desde la red y ya terminó, ¿tiene alguna consecuencia que el recurso no se cierre? Ciertamente, no cambia nada en el programa. – Yishai

+0

a menos que deje el puerto abierto e inutilizable para cualquier otra persona –

4

Commons-io también tiene closeQuietly() para las transmisiones de entrada y salida. Lo estoy usando todo el tiempo. Hace que tu código sea mucho más legible.

12

Como han mencionado otros, una utilidad estática closeQuietly es el camino a seguir. Una cosa a añadir - si usted está en el mundo de la java.io en lugar de java.sql entonces hay una interfaz útil precisamente para este propósito - java.io.Closeable

Todas las fuentes de datos y los sumideros en java.io implementan esta interfaz - todos los arroyos, canales, escritores y lectores De esta forma, puede crear una sola utilidad para hacer frente al mismo problema de "excepción al cerrar()" sin requerir muchas versiones sobrecargadas.

p. Ej.

public class IoUtils { 

    public static closeQuietly (Closeable closeable) { 
    try { 
     closeable.close(); 
    } catch (IOException logAndContinue) { 
     ... 
    } 
    } 

} 
0

También hay método práctico Closeables # closeQuitely en la biblioteca de Google Guava - que puede ser utilizado para cualquier closeable

0

¿Podemos tener un bloque try seguido por fin Bock y captura cuadra después de eso?

1

Sólo una nota rápida para decir que con Java 7 (y 8), en su lugar puede escribir:

public void java7() throws SQLException { 
    try (Connection connection = Connections.openConnection(); 
     CallableStatement callableStatement = connection.prepareCall("my_call"); 
     ResultSet resultSet = callableStatement.executeQuery()) { 

     while (resultSet.next()) { 
      String value = resultSet.getString(1); 
      System.out.println(value); 
     } 
    } 
} 

en lugar de la versión Java 6, que tiene todas estas líneas:

public void java6() throws SQLException { 
    Connection connection = Connections.openConnection(); 
    try { 
     CallableStatement callableStatement = connection.prepareCall("my_call"); 
     try { 
      ResultSet resultSet = callableStatement.executeQuery(); 
      try { 
       while (resultSet.next()) { 
        String value = resultSet.getString(1); 
        System.out.println(value); 
       } 
      } finally { 
       try { 
        resultSet.close(); 
       } catch (Exception ignored) { 
       } 
      } 
     } finally { 
      try { 
       callableStatement.close(); 
      } catch (Exception ignored) { 
      } 
     } 
    } finally { 
     try { 
      connection.close(); 
     } catch (Exception ignored) { 
     } 
    } 
} 
Cuestiones relacionadas