public <T> T execute(ConnectionCallback<T> action) throws DataAccessException {
Assert.notNull(action, "Callback object must not be null");
Connection con = DataSourceUtils.getConnection(getDataSource());
try {
Connection conToUse = con;
if (this.nativeJdbcExtractor != null) {
// Extract native JDBC Connection, castable to OracleConnection or the like.
conToUse = this.nativeJdbcExtractor.getNativeConnection(con);
}
else {
// Create close-suppressing Connection proxy, also preparing returned Statements.
conToUse = createConnectionProxy(con);
}
return action.doInConnection(conToUse);
}
catch (SQLException ex) {
// Release Connection early, to avoid potential connection pool deadlock
// in the case when the exception translator hasn't been initialized yet.
DataSourceUtils.releaseConnection(con, getDataSource());
con = null;
throw getExceptionTranslator().translate("ConnectionCallback", getSql(action), ex);
}
finally {
DataSourceUtils.releaseConnection(con, getDataSource());
}
}
回答
根據在catch (SQLException ex)
塊的評論,誰寫了這個代碼是考慮到下面的行可能花一些時間在其初始調用運行:
throw getExceptionTranslator().translate("ConnectionCallback", getSql(action), ex);
當的SQLException得到翻譯,他們不希望連接仍然會不必要地舉行;因此,他們首先發布它。
請記住,雖然翻譯的期望將被拋出,但finally塊中的代碼將在異常拋出給調用方之前運行;然而,finally塊,這些方法後,將運行要求:getExceptionTranslator().translate("ConnectionCallback", getSql(action), ex)
另一種方式看到這是一個具有以下,相當於代碼:
catch (SQLException ex) {
// Release Connection early, to avoid potential connection pool deadlock
// in the case when the exception translator hasn't been initialized yet.
DataSourceUtils.releaseConnection(con, getDataSource());
con = null;
// create the translated exception
Exception et = getExceptionTranslator().translate("ConnectionCallback", getSql(action), ex);
// throw the translated exception
throw et;
}
finally {
// release the connection.
// If a SQLException is caught above, then this will run before
// the translated exception is thrown to the caller
DataSourceUtils.releaseConnection(con, getDataSource());
}
此外,他們想通它不會傷害嘗試即使它已經在catch塊中釋放,也可以在finally塊中再次釋放連接。這假設釋放一個已經釋放或空的連接沒有效果。
還值得注意的是,無論拋出try塊中的SQLException,您仍然想嘗試釋放連接。因此,需要在finally塊中這樣做。
//儘早釋放連接,以避免在異常轉換程序尚未初始化的情況下潛在的連接池死鎖。 哪種情況會導致連接池死鎖? – levy
不知道它是否會導致連接池死鎖 - 這實際上只是將連接早於連接池而不是後面的事情,以便其他線程在等待連接時等待更少的時間。 –
- 1. 爲什麼它總是捕捉塊並且不執行「cmd.ExecuteNonQuery();」
- 2. 最後一塊的執行
- 3. 執行'閱讀器'去捕捉塊
- 4. 爲什麼在javascript中執行模塊模式時執行自我執行
- 5. 爲什麼finally塊不能執行?
- 6. 在Java中執行新操作後,代碼塊會執行什麼操作?
- 7. 爲什麼finally塊在調用sys.exit(0)之後在except塊中執行?
- 8. 執行塊後執行塊中的一段代碼
- 9. 爲什麼這最後不能執行?
- 10. 爲什麼最後不會執行?
- 11. 執行程序關閉後,爲什麼Runnable仍然在可執行的線程池執行程序中執行?
- 12. finally塊最後執行的原因是什麼?
- 13. SourceTree子模塊更新 - 爲什麼執行?
- 14. Java:爲什麼循環中的try-catch塊只執行一次?
- 15. 爲什麼靜態塊中的代碼不執行?
- 16. 爲什麼子類中的靜態塊沒有被執行?
- 17. 爲什麼在BEGIN塊中首先執行'use'語句?
- 18. 爲什麼我不能在匿名plpg塊中執行函數?
- 19. 爲什麼在執行內部塊之後,scala函數中的塊變量無法更新?
- 20. 塊的執行流程是什麼?
- 21. 最後執行jQuery代碼塊
- 22. 爲什麼catch程序塊爲單個異常執行兩次?
- 23. 執行後無法捕捉信號
- 24. 時拋出新的錯誤()被寫在try塊,爲什麼不執行catch塊。它進入最後只能.Latter代碼也不會執行
- 25. 捕獲塊行爲
- 26. 嘗試捕捉執行
- 27. 執行捕捉優先級
- 28. 爲什麼我的JavaScript Catch塊不能執行?
- 29. CATCH塊不會第一次執行,而是第二次執行 - 爲什麼?
- 30. C++程序終止而不執行捕捉塊
我認爲「releaseConnection」只需要在finally {}塊中執行,不是嗎? – levy
你的意思是,爲什麼在這兩個地方都有一個對'releaseConnection'的調用? –
是的,我不明白 – levy