1. 程式人生 > >finally被置空導致資料庫連線掛死

finally被置空導致資料庫連線掛死

        今天寫了幾行程式碼,向資料庫插入一篇文章,程式執行表現很好,完全按照我的意願去走,可以寫入時都成功寫入資料庫,該失敗時果斷失敗。可是當我回頭再看程式碼時,突然驚恐萬分。這裡面隱藏了多麼弱智的bug,甚至說是外行的錯誤,可是想了一下,似乎又很有可能出現,一不小心就有可能再次寫出來,所以寫個博警告下自己。

        向資料庫插入文章的程式碼,這裡面至少隱藏了三個超級弱智的致命錯誤:

public int insertThreadBeanIntoDB(ThreadBean threadbean){

ErrorTypeBean ErrorType  = ErrorTypeBean.getErrorTypeHandle();

/*這一步是必須做的,否則會出異常*/

if(null == threadbean){

return ErrorType.getErrorCodeByErrorType("NULL_POINTER");

}

Connection conn   = null;

PreparedStatement  ps       = null;

int              result = 0;

try{

conn = new ConnDB().getConnection();

ps = conn.prepareStatement("insert into thread values(?,?,?,?,?,?,?)");

ps.setString(1, threadbean.getThread_id().toString());

ps.setString(2, threadbean.getTread_title());

ps.setString(3, threadbean.getTread_content());

ps.setString(4, threadbean.getThread_create_time().toString());

ps.setString(5, threadbean.getThread_update_time().toString());

ps.setString(6, threadbean.getThread_hit_number().toString());

ps.setString(7, threadbean.getThread_user().toString());

result=ps.executeUpdate();

if(0 == result){

return  ErrorType.getErrorCodeByErrorType("DB_OPERATION_ERROE");

}

}catch(Exception e){

e.printStackTrace();

return ErrorType.getErrorCodeByErrorType("UNKNOWN_ERROR");

}finally{

/*關閉資源*/

this.closeConn();

}

return ErrorType.getErrorCodeByErrorType("NO_ERROR");


}

在try裡面成功操作資料庫後,直接將結果返回;

catch到異常後直接返回錯誤碼;

在程式的最後直接返回成功。

嚴重沒睡醒!

        無論是在在try裡面還是在catch裡面返回,都會講finally掛起,導致資料庫連線無法關閉。在上面的寫法下,如果出現錯誤,catch會攔截下來,所以出現錯誤的時候不會有任何不正常的表現,但是finally被置空了;而如果執行成功,則catch無效,可以在最後返回成功,程式也不會出現表面的失敗。而一旦try裡面的返回條件滿足,則try就會將finally置空,撇開上面的try裡面的情況,如果稍微處理複雜點,可能會出現,在操作成功的時候也會全部將finally置空,這時,finally將永遠得不到執行,所有資料庫連線將全部不能關閉。

        這種錯誤在執行的時候不會出現任何異常表現,一旦時過境遷,這種錯誤將無從查起,而系統頻繁出現數據庫自然耗盡,解決辦法只有重啟...重啟...再重啟。當然了,也可以通過檢視資料庫連線的使用情況來分析問題的所在。但是問題已經升級不止一個檔次了,小疏忽引發的大問題,不可疏忽。

        正確寫法:

public int insertThreadBeanIntoDB(ThreadBean threadbean){

ErrorTypeBean ErrorType                         = ErrorTypeBean.getErrorTypeHandle();

int                        operation_code              = ErrorType.getErrorCodeByErrorType("NO_ERROR");

/*這一步是必須做的,否則會出異常*/

if(null == threadbean){

return ErrorType.getErrorCodeByErrorType("NULL_POINTER");

}

Connection  conn   = null;

PreparedStatement  ps       = null;

int              result = 0;

try{

conn = new ConnDB().getConnection();

ps = conn.prepareStatement("insert into thread values(?,?,?,?,?,?,?)");

ps.setString(1, threadbean.getThread_id().toString());

ps.setString(2, threadbean.getTread_title());

ps.setString(3, threadbean.getTread_content());

ps.setString(4, threadbean.getThread_create_time().toString());

ps.setString(5, threadbean.getThread_update_time().toString());

ps.setString(6, threadbean.getThread_hit_number().toString());

ps.setString(7, threadbean.getThread_user().toString());

result=ps.executeUpdate();

if(0 == result){

operation_code  = ErrorType.getErrorCodeByErrorType("DB_OPERATION_ERROE");

}

}catch(Exception e){

e.printStackTrace();

operation_code  = ErrorType.getErrorCodeByErrorType("UNKNOWN_ERROR");

}finally{

/*關閉資源*/

this.closeConn();

}

return operation_code;


}

如果非得在try-catch裡面返回,name至少應該寫在finally裡面,寫在關閉資料庫連線之後。