2009-08-26 37 views
30

tôi đã thường xuyên gặp tình huống như: -Hãy thử-catch-cuối cùng và sau đó một lần nữa cố gắng nắm bắt

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

mà vẫn cần một thử - khối catch bên cuối cùng.

Cách tốt nhất để khắc phục điều này là gì?

+0

Bạn có thể thấy rằng việc mua lại tài nguyên cũng như vậy. (Vì vậy, thực sự sử dụng câu trả lời của seth.) –

Trả lời

23

Viết SQLUtils lớp có chứa static closeQuietly các phương pháp bắt và ghi lại ngoại lệ như vậy, sau đó sử dụng khi thích hợp.

Bạn sẽ kết thúc với một cái gì đó mà đọc như thế này:

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

Và mã khách hàng của bạn sẽ được một cái gì đó như:

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

Đây là sự lựa chọn của tôi cũng như trong quá khứ, nhưng tôi đã tìm thấy những ngày này rằng có những lớp học, như apache commons DBUtil, mà làm điều này cho bạn. –

+0

trông giống như một lựa chọn tốt :) Cảm ơn – Ajay

10

Tôi thường làm điều đó theo cách này:

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

Tôi thường chỉ được sử dụng điều này khi tôi đã không sử dụng một thư viện mà đã chăm sóc hệ thống ống nước này đối với tôi.

Khi Imagist chỉ ra, đây không phải là kỹ thuật giống như cuối cùng sẽ chạy trước khi bắt nhưng tôi nghĩ nó giải quyết được vấn đề bạn đang cố giải quyết.

+0

Đó không phải là kỹ thuật giống nhau, nhưng tùy thuộc vào tình hình nó có thể làm những gì Ajay muốn. – Imagist

+0

@Imagist: Tốt. Tôi sẽ cập nhật câu trả lời của mình. Cảm ơn. – seth

+0

Bạn có thể tất nhiên sau đó trừu tượng rằng với thành ngữ Execute Around. –

1

Đừng ngần ngại sử dụng thêm một thử ... bắt bên trong cuối cùng.

-1

chỉ nhớ .. cuối cùng luôn luôn được thực hiện một trong hai với thử hoặc bắt ..

+0

Điểm của bạn là? –

+0

không nhận được điểm của bạn – Ajay

0

Nói chung, bạn không muốn làm bất cứ điều gì hơn đăng nhập một ngoại lệ đó sẽ xảy ra khi đóng cửa một nguồn tài nguyên, vì vậy nó thực sự nên đi trong thử/nắm bắt riêng của nó. Tuy nhiên, đây là mã chung sẽ xảy ra thường xuyên, vì vậy đừng lặp lại chính mình, và đóng một phương thức tĩnh (như Nick Holt gợi ý) theo cách đó bạn sẽ không có hai mục try/catch trong cùng một phương thức, làm cho mã dễ đọc và dễ theo dõi hơn.

+0

Tôi không chắc chắn rằng tôi đồng ý với điều đó. Theo tôi, việc không đóng tài nguyên thể hiện một vấn đề nghiêm trọng hơn là một ngoại lệ điển hình sẽ xảy ra trong quá trình sử dụng. Người ta nên nỗ lực để giữ cho các ngoại lệ bên trong (dễ dàng hơn trong vb.net hơn C#) nhưng ném một "nghiêm trọng hơn" một. – supercat

+0

Nếu bạn đang đọc từ mạng và bạn đã hoàn tất, có thực sự do bất kỳ hậu quả nào mà tài nguyên không đóng được không? Nó chắc chắn không thay đổi bất cứ điều gì về chương trình. – Yishai

+0

trừ khi nó rời khỏi cổng mở và không sử dụng được cho bất kỳ ai khác –

4

Commons-io cũng có closeQuietly() cho luồng vào và ra. Tôi sử dụng nó mọi lúc. Nó làm cho mã của bạn dễ đọc hơn nhiều.

12

Như những người khác đã đề cập, tiện ích tĩnh closeQuietly là cách để thực hiện. Một điều cần thêm - nếu bạn đang ở trong thế giới của java.io hơn java.sql sau đó là một giao diện hữu ích cho chính xác mục đích này - java.io.Closeable

Tất cả các nguồn dữ liệu và chìm trong java.io thực hiện giao diện này - tất cả các con suối, kênh, nhà văn và độc giả. Bằng cách đó, bạn có thể tạo ra một tiện ích duy nhất để đối phó với cùng một "ngoại lệ về vấn đề close()" mà không đòi hỏi nhiều phiên bản quá tải.

ví dụ:

public class IoUtils { 

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

} 
0

Ngoài ra còn có phương pháp Closeables # closeQuitely tiện dụng trong thư viện Google Ổi - nó có thể được sử dụng cho bất kỳ có thể đóng

0

có thể, chúng tôi đã cố gắng ngăn chặn tiếp theo cuối cùng Bock và khối catch sau đó?

1

Chỉ cần một lưu ý nhanh chóng để nói rằng với Java 7 (và 8), bạn thay vì có thể viết:

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

chứ không phải là phiên bản Java 6 trong đó có tất cả các dòng:

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) { 
     } 
    } 
} 
Các vấn đề liên quan