2009-10-30 128 views
1

我正在使用休眠3與c3p0的程序,它不斷從某些源提取數據並將其寫入數據庫。 現在的問題是,數據庫可能由於某些原因而變得不可用(在最簡單的情況下:我只是關閉它)。休眠c3p0斷管

如果有什麼要寫入數據庫,則不應該有任何異常 - 查詢應等待所有永久性,直到數據庫再次可用。 如果我沒有弄錯,這是連接池可以爲我做的事情之一:如果數據庫有問題,只需重試連接 - 在最壞的情況下爲無窮大。

但是,相反,我得到一個破損的管道異常,有時跟在拒絕連接,然後異常傳遞給我自己的代碼,這不應該發生。

即使我發現異常,我又能幹淨地重新初始化休眠嗎? (到目前爲止,沒有c3p0,我只是再次構建會話工廠,但如果可能會泄漏連接(或者可以這麼做),我不會感到驚訝)。

該數據庫是Virtuoso開源版本。

我hibernate.xml.cfg C3P0的配置:

<property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property> 
<property name="hibernate.c3p0.breakAfterAcquireFailure">false</property> 
<property name="hibernate.c3p0.acquireRetryAttempts">-1</property> 
<property name="hibernate.c3p0.acquireRetryDelay">30000</property> 
<property name="hibernate.c3p0.automaticTestTable">my_test_table</property> 

<property name="hibernate.c3p0.initialPoolSize">3</property> 
<property name="hibernate.c3p0.minPoolSize">3</property> 
<property name="hibernate.c3p0.maxPoolSize">10</property> 

BTW:測試表創建和我得到噸調試輸出 - 如此看來,它實際上讀取配置。

回答

3

如果我沒有弄錯,這是連接池可以爲我做的事情之一:如果數據庫有問題,只需重試連接 - 在最壞的情況下爲無窮大。

你錯了。連接池就是......連接池,它包含一些已建立的數據庫物理連接,用於避免在需要其中一個連接時創建這些連接的開銷。

也就是說,這些連接可能會變陳舊(例如,如果您重新啓動數據庫)。幸運的是,大多數連接池都可以配置爲測試連接是否仍然有效,並在分發它們之前更新它們。 c3p0支持此功能,如Configuring Connection Testing中所述,您實際上已經在使用其中一種選項。因此,當數據庫恢復時,連接應該更新。

但是,不要指望你的應用程序在數據庫發生故障時被神奇地掛起,一個池不會這樣做。

0

謝謝你的回答。 看來我只是還沒有真正理解該節末段 http://www.mchange.com/projects/c3p0/index.html#configuring_recovery

因爲起初似乎C3P0能做到這一點(檢測失效連接並重新獲得了永恆的連接而沒有拋出異常的應用程序代碼(當然,除非它的錯誤與sql語句相關,而與連接無關),但在最後一段 - 以相當混亂的方式寫入 - 看起來好像c3p0不能確保達到100%。

所以我的解決方案是從jdbc連接接口爲我需要的方法創建一個小包裝器,如果由於連接錯誤而導致查詢失敗,它將嘗試重新連接,當然它有點hac ky,因爲我寧願讓我的組件使用標準的Connection-interface來代替我自己的界面,但至少現在它的工作很乾淨。

0

你忘了:

  • 關於您的交易是什麼已經開始了嗎?
  • 那麼已經發送到數據庫的任何準備狀態如何?因此

您的應用程序將不得不重新啓動事務。我能想到的唯一可能的方式是連接池跟蹤對連接句柄的每個調用,並在出現錯誤時重播這些句柄,但這會大大降低連接緩衝池的速度。

在BoneCP(http://jolbox.com)的情況下,池通過捕獲JDBC驅動程序首先拋出的異常並通過將該連接標記爲有故障或重新創建整個連接池來處理它,從而檢測到發生了故障。

編輯:現在正在處理。

+0

是的,我現在看到,這種簿記可能對例如之上實現一個連接池,但它超出了這個池的範圍。 – 2009-11-13 13:23:23