2012-06-22 41 views
7

我是Java新手(我正在使用Java 6)。我一直在使用以下設計模式來處理所有Java POJO和servlet,以通過GlassFish 3.1.2 Web服務器訪問Oracle 11G數據庫。Java/JDBC:發生異常時關閉數據庫連接的最佳設計模式

當所有可用的進程(或會話,不知道有什麼區別)被使用時,我得到一個間歇性的數據庫錯誤(ORA-12519),導致我以某種方式認爲應用程序沒有釋放進程。

看看下面的設計模式,有沒有更好的方法來確保在發生異常時發佈到數據庫的JDBC連接?例如,我是否也應該將if (conn != null) conn.close();代碼放在catch塊中?或者,有沒有更好的設計模式?提前感謝您的任何意見/提示。

public String MyFunction() throws Exception {  

    Connection conn; 
    CallableStatement cs; 

    try { 

     Context context = new InitialContext(); 
     DataSource ds = (DataSource)context.lookup("jdbc/MyPool"); 
     conn = ds.getConnection();   

     cs = conn.prepareCall("{call my_sproc (?)}"); 

     cs.registerOutParameter(1, Types.VARCHAR); 

     cs.execute(); 

     String outParam = cs.getString(1); 

     if (conn != null) // close connection 
     conn.close(); 

    } catch (Exception e) { 
     outParam = "an error occurred"; 
    } 
    return outparam; 
} 
+0

注意,也可能是很好的做法,關閉結果集和語句。這裏有一個有用的鏈接(請參閱Stefan Schweizer在良好設計模式鏈接中的回覆):http://stackoverflow.com/questions/103938/resultset-not-closed-when-connection-closed – ggkmath

回答

29
if (conn != null) // close connection 
     conn.close(); 

在這條線conn不能爲空。最流行的模式,直到Java 6的是:

Connection conn = null; 
try { 
    // initialize connection 
    // use connection 
} catch { 
    // handle exception 
} finally { 
    if (conn != null) { 
    try { conn.close(); } catch (Exception e) { /* handle close exception, quite usually ignore */ } 
    } 
} 

隨着的Java 7,這將成爲其try-with-resource結構不太麻煩。上面的代碼可以更改得更短

try (Connection conn = createConnection()) { 
    // use connection 
} catch { 
    // handle exception 
} 
// close is not required to be called explicitly 
+1

感謝Miserable Variable,當你說「直到Java 6」,你的意思是「直到幷包括Java 6」(這就是我正在使用的)?我假設如此。另外,當你說「經常被忽略」時,你是否僅僅引用finally塊中的try ... catch(即,「if(conn!= null)conn.close();'總是那裏,對嗎?)?爲什麼人們通常忽略處理關閉連接的finally塊中的異常? – ggkmath

+0

是的,來自'connection.close()'的異常經常被忽略或者最多被記錄,但是沒有以任何其他方式處理:)我不知道爲什麼;我從來沒有見過近距離拋出異常。 –

+0

好吧,我可能會記錄它,謝謝! – ggkmath

4

總是使用finally塊來釋放資源。

finally塊總是在try塊退出時執行。這可確保即使發生意外異常也能執行finally塊。

try { 

     Context context = new InitialContext(); 
     DataSource ds = (DataSource)context.lookup("jdbc/MyPool"); 
     conn = ds.getConnection();   

     cs = conn.prepareCall("{call my_sproc (?)}"); 

     cs.registerOutParameter(1, Types.VARCHAR); 

     cs.execute(); 

     String outParam = cs.getString(1); 


    } catch (Exception e) { 
     outParam = "an error occurred"; 
    } 
finally { 
     conn.close(); 
    } 
+0

謝謝Kazekage,請問conn。如果連接尚未打開或其他原因,finally塊中的close()行代碼會產生錯誤?如果是這樣,我不應該在finally塊中使用'if(conn!= null)'語句嗎? – ggkmath

+0

如果您懷疑'conn.close()'會再次發出錯誤,那麼最後還要用'try catch'來包圍它。 –

+1

@ggkmath是的,你需要測試'conn!= null';如果'ds.getConnection()'拋出異常,它可以爲空。不管你是否懷疑,你需要在'try/catch/finally'中放置'close()';否則該方法必須將其引入「拋出」條款中,這是不好的。 –

2

java se 7支持try-with-resources功能。爲你生成最後的結果。 http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html

finally塊會關閉try中的資源。就像你正在使用使用C#

但用戶正在使用的Java SE6關鍵字...查看其他用戶:)

重要的選擇:使用也應該被關閉的發言。

+0

對於java 7用戶很有參考價值,謝謝! – ggkmath

+0

我沒有閱讀,但用戶悲慘變量也談到了試用資源。 – brunoss

+0

我會確認在1分鐘內,但我想你需要關閉陳述 – brunoss