2009-08-26 8 views
30

mam często natknąć sytuacjach, takich jak: -Try-catch-finally, a następnie ponownie połów try

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

który musi jeszcze spróbować - blok catch wewnątrz wreszcie.

Jaka jest najlepsza praktyka do pokonania tego?

+0

Prawdopodobnie odkryjesz, że pozyskiwanie zasobów również się rzuca. (Tak naprawdę używaj odpowiedzi seth'a.) –

Odpowiedz

23

Napisz klasę , która zawiera static closeQuietly metody przechwytujące i rejestrujące takie wyjątki, a następnie użyj ich w razie potrzeby.

Będziesz skończyć z czymś, co brzmi tak:

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); 
    } 
    } 
} 

i kod klienta będzie coś takiego:

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

To jest również mój wybór w przeszłości, ale znalazłem te dni, że istnieją klasy, takie jak Apache commons DBUtil, które robią to za ciebie. –

+0

wygląda na dobrą opcję :) Dzięki – Ajay

10

zwykle zrobił to w ten sposób:

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

zwykle używany to tylko wtedy, kiedy nie był przy użyciu biblioteki, który opiekował tej kanalizacji dla mnie.

Jak wskazuje Imagist, nie jest to technicznie takie samo, jak ostatecznie będzie działać przed połowem, ale myślę, że rozwiązuje problem, który próbujesz rozwiązać.

+0

To nie jest technicznie takie samo, ale w zależności od sytuacji może robić to, czego chce Ajay. – Imagist

+0

@Imagist: Dobra uwaga. Zaktualizuję moją odpowiedź. Dzięki. – seth

+0

Możesz oczywiście to zedytować za pomocą języka Execute Around. –

1

nie wahaj wykorzystanie jeszcze spróbować ... złap się w końcu.

-1

tylko pamiętać .. w końcu zawsze się wykonać albo z próby lub połowu ..

+0

Twoim celem jest? –

+0

Nie uzyskałem punktu – Ajay

0

Generalnie nie chcesz robić nic więcej niż log wyjątek co zdarza się przy zamykaniu zasób, więc powinien naprawdę iść w własna próba/połów. Jest to jednak kod generyczny, który będzie się często zdarzał, więc nie powtarzaj się i zamknij w statycznej metodzie (jak sugeruje Nick Holt) w ten sposób, że nie będziesz mieć dwóch elementów try/catch w tej samej metodzie, uczynienie kodu łatwiejszym do odczytania i naśladowania.

+0

Nie jestem pewien, czy się z tym zgadzam. Moim zdaniem niepowodzenie zamknięcia zasobu stanowi poważniejszy problem niż typowy wyjątek, który wystąpiłby podczas użytkowania. Należy starać się zachować wyjątek wewnętrzny (łatwiejszy w vb.net niż C#), ale rzucać "surowszy". – supercat

+0

Jeśli czytasz z sieci i skończyłeś, czy naprawdę nie można zamknąć zasobu? Z pewnością nic nie zmienia w programie. – Yishai

+0

, chyba że pozostawia port otwarty i nie nadaje się do użytku dla nikogo innego –

4

Commons-io również ma closeQuietly() dla strumieni wejściowych i wyjściowych. Używam go cały czas. To sprawia, że ​​twój kod jest znacznie bardziej czytelny.

12

Jak już wspomnieli inni, narzędzie statyczne closeQuietly jest drogą do zrobienia. Jedną rzeczą, aby dodać - jeśli jesteś w świecie java.io zamiast java.sql wtedy jest użyteczny interfejs do dokładnie tego celu - java.io.Closeable

Wszystkie źródła danych oraz umywalki w java.io wdrożyć ten interfejs - wszystkie strumienie, kanały, pisarze i czytelnicy. W ten sposób można utworzyć pojedyncze narzędzie, które poradzi sobie z tym samym problemem "wyjątek przy zamknięciu()", nie wymagając wielu przeciążonych wersji.

np.

public class IoUtils { 

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

} 
0

Jest również przydatny sposób Closeables # closeQuitely w bibliotece Google Guava - może być stosowany dla każdego zamykane

0

możemy mieć blok try następnie wreszcie Bock i złapać bloku później do tego?

1

Wystarczy krótka notatka powiedzieć, że z Java 7 (i 8), można zamiast pisać:

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); 
     } 
    } 
} 

zamiast wersji Java 6, który ma wszystkie te linie:

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) { 
     } 
    } 
} 
Powiązane problemy