2009-08-26 32 views
30

我經常遇到的情況,如: -的try-catch-finally程序,然後再次嘗試捕捉

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

仍然需要一個try - catch塊內最後。

什麼是克服這種最好的做法?

+0

您可能會發現資源獲取也會拋出。 (所以真的使用seth的答案。) – 2009-08-26 16:34:21

回答

23

編寫一個SQLUtils類,其中包含static closeQuietly方法,用於捕獲並記錄這些異常,然後酌情使用。

你最終的東西,上面寫着這樣的:

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

和你的客戶端代碼將是這樣的:

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

這是我的選擇,以及在過去,但我發現,這些天有課,如Apache公地DBUtil,爲你做到這一點。 – 2009-08-26 16:57:16

+0

看起來像一個不錯的選擇:)謝謝 – Ajay 2009-08-27 04:11:07

10

我通常就是這麼做的:

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

當我不使用照顧這個管道的對我來說是圖書館中,我通常只用這個。

由於Imagist指出,這在技術上並不相同,最終將在catch之前運行,但我認爲它解決了您試圖解決的問題。

+0

這在技術上並不相同,但根據情況它可能會做Ajay想要的。 – Imagist 2009-08-26 16:07:52

+0

@Imagist:好點。我會更新我的答案。謝謝。 – seth 2009-08-26 16:26:46

+0

你當然可以用Execute Around idiom來抽象。 – 2009-08-26 16:33:06

1

不要猶豫使用一次機會...最後抓到裏面。

-1

只記得..最後總是要麼嘗試或趕上執行..

+0

您的觀點是? – 2009-08-26 17:12:04

+0

沒有得到您的觀點 – Ajay 2009-08-29 08:22:58

0

一般來說,你不想做任何事情超過登錄關閉資源時發生了異常,因此它應該去的它自己的嘗試/抓住。但是,這是通常會發生的通用代碼,因此不要重複自己,並且將close放在靜態方法中(正如Nick Holt所建議的那樣),以這種方式,您不會使用同一方法中的兩個try/catch項目,使代碼更易於閱讀和遵循。

+0

我不確定我是否同意這一點。在我看來,未能關閉資源代表比使用過程中發生的典型異常更嚴重的問題。一個人應該努力保持內部的異常(在vb.net比C#更容易),但拋出一個「更嚴重」的。 – supercat 2010-12-17 03:04:58

+0

如果您正在從網絡中讀取並完成,資源未能關閉是否有任何後果?這當然不會改變有關該計劃的任何內容。 – Yishai 2010-12-21 13:38:19

+0

,除非它將端口打開並對其他人無法使用 – 2012-02-01 22:56:50

4

共享-IO還具有closeQuietly()在和輸出流。我一直在使用它。它使你的代碼更具可讀性。

12

正如其他人所說,靜態closeQuietly效用是要走的路。有一點要補充 - 如果你是在java.io而非java.sql世界上再有就是出於這樣的目的一個有用的接口 - java.io.Closeable

所有java.io的數據源和接收器實現這個接口 - 所有的流,渠道,作家和讀者。通過這種方式,您可以創建單個實用程序來處理相同的「close()」異常問題,而不需要許多重載版本。

例如

public class IoUtils { 

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

} 
0

還有方便Closeables#closeQuitely方法在谷歌番石榴庫 - 它可以被用於任何可關閉

0

我們可以接着終於博克和catch塊之後到try塊?

1

只是一個快速照會說,與Java 7(8),你可以代替寫:

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

,而不是它擁有所有這些線路的Java 6的版本:

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