java.sql.SQLException: connection holder is null

 

調試的時候常常會出現這個問題,緣由是事務時間已經達到系統設置的最長值,系統覺得超時,切斷這個鏈接,從而調用事務時發生了錯誤。java

這個不單單是調試時會發生,再系統中也有發生,好比一個很耗時的流程,由於過程很是耗時,這個耗時操做剛好是在service的事務中發生,事務打開鏈接必然打開,因此他就會暫用鏈接的大量時間,致使系統耗時過長(達到鏈接時長的最大值)而鏈接斷開。spring

或許你會想到調整這個耗時時長:數據庫

spring-mybatis.xml服務器

<!-- 清除無用鏈接的等待時間 --> 網絡

<property name="removeAbandonedTimeout" value="600"/>mybatis

 

另外,對於一些數據庫鏈接耗時很長的操做,咱們能夠經過 Mybatis 單獨設置這個時間,select update insert delete調試

timeout 這個設置是在拋出異常以前,驅動程序等待數據庫返回請求結果的秒數。默認值爲 unset(依賴驅動)。xml

 

缺陷,因爲大部分系統使用聲明式事務(Spring的AOP),而非註解式事務(@Transaction),致使全部的非數據庫的業務邏輯都用在了事務上,由於事務是加在 Service上,Service就是全部的業務代碼集合,因此,不少非數據庫操做的邏輯都加了事務,其實徹底沒有必要。若是咱們使用註解式事務,那麼一些邏輯操做是可控的。事務

    <tx:advice id="txAdvice" transaction-manager="transactionManager">資源

        <tx:attributes>

            <tx:method name="add*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>

            <tx:method name="delete*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>

            <tx:method name="insert*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>

            <tx:method name="update*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>

            <tx:method name="save*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>

            <tx:method name="set*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>

        </tx:attributes>

    </tx:advice>

 

鏈接時間太長致使資源浪費,並且超時是一個很友好的設置,若是沒有超時設置,無限制等待,雖然能夠解決耗時問題,可是若是遇到系統錯誤,那就會一直等待,暫用資源。

好比這段代碼

// 客戶端代碼

try{

    process() 

    notifyServer()

}catch(Exception e ){

   // do nothing 

}

假設這樣的處境,服務端想要知道客戶端的座標,發送一個長鏈接給客戶端,客戶端就會執行如上的代碼,先去 process 獲取當前座標,而後通知服務器。若是,客戶端在獲取座標的時候出現了Exception,好比 GPS信號弱,網絡不通等,那麼客戶端拋出異常被捕獲,客戶端仍是順利的執行了代碼,卻沒有通知服務端,咱們這裏發生了異常。那麼這個時候服務端一直等待客戶端的響應,沒有超時設置的話,一直佔用這個鏈接,若是有超時的話,達到這個時間,鏈接就斷開了。

相關文章
相關標籤/搜索