2017-06-19 51 views
0
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()); 
    } 
} 
+0

我認爲「releaseConnection」只需要在finally {}塊中執行,不是嗎? – levy

+0

你的意思是,爲什麼在這兩個地方都有一個對'releaseConnection'的調用? –

+0

是的,我不明白 – levy

回答

2

根據在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塊中這樣做。

+0

//儘早釋放連接,以避免在異常轉換程序尚未初始化的情況下潛在的連接池死鎖。 哪種情況會導致連接池死鎖? – levy

+0

不知道它是否會導致連接池死鎖 - 這實際上只是將連接早於連接池而不是後面的事情,以便其他線程在等待連接時等待更少的時間。 –

相關問題