2011-12-08 25 views
0

我有一個GWT應用程序,它使用休眠來連接到postgres數據庫。當我在更快的服務器上運行tomcat中的應用程序時,我注意到了一個問題。Postgres保存數據比休眠讀取值更慢

我的應用程序中的一個視圖從數據庫加載舊數據。那麼發生了什麼?在視圖中,用戶可以輸入一些數據,然後他點擊保存按鈕。這會導致一個異步調用,通過休眠將數據保存到postgres中。只要我在代碼中執行commit()(我將lazy update設置爲false),我就從異步調用返回,然後對視圖進行刷新(=從db重新加載數據並顯示它)。這導致重新讀取來自db的數據。但是,該視圖有時會顯示舊數據。然後我再次刷新視圖,我可以看到正確的當前數據。我的猜測是,hibernate的commit()函數導致異步調用,因此我比第一次異步調用(當用戶點擊保存按鈕時)早一些回來,而不是將數據保存到postgres。因此該視圖加載舊數據。

有沒有人有類似的問題,休眠和postgres?

回答

0

您的解釋不正確。 Hibernate事務的提交不會寫入並提交到數據庫,如果提交成功,那麼數據將在數據庫中提交。

您所看到的來自其他地方:瀏覽器緩存或二級緩存(如果配置不正確(例如,只讀模式))。

另一種解釋是,第二個異步調用在發送到服務器之前不會等待第一個異步調用完成。

+0

第一次異步調用在調用commit()完成時完成。但是,如果函數commit()正在另一個線程中執行,那麼可能會導致該問題。瀏覽器無法緩存數據,因爲每次我從數據庫顯式加載數據。 – mkn

+1

提交不是異步的。如果是的話,它不會再被稱爲交易。 –

2

Hibernate的二級緩存並不捕獲通過視圖,原生查詢等發生的基礎實體發生的數據庫更新。我會說你被這個咬傷了,並且需要顯式地使緩存失效當你知道你已經破壞它,或需要禁用它。

另一種可能性是,您正在使用SERIALIZABLE事務隔離模式,並且打開一箇舊事務的連接。假設您的應用程序正在從連接池或應用程序的其他部分獲取連接,並且該連接已經在寫入您正在嘗試閱讀的數據之前進行了打開事務。如果是這樣的話,你會看到一箇舊的快照。這不應該發生,但有問題的應用程序可以返回與池的打開事務的連接,並且池可能未設置爲自動關閉並重置它們,或者您可能沒有使用正確的連接池。

在這兩者中,我認爲Hibernate緩存問題更可能是罪魁禍首。

+0

謝謝你分享你的想法。我可以問你我需要禁用緩存嗎?這是一個普通的配置,還是可以按照每個表格進行管理? – mkn

+1

@mkn:請參閱Hibernate文檔中的「第二級緩存」。您可以通過屬性將其設置在持久性單元級別。具體如何根據版本以及如何使用Hibernate來直接或通過JPA的persistence.xml來變化版本。 如果禁用二級緩存可修復您的問題,則不一定要保留該問題。找出哪些查詢或多個查詢繞過緩存,並查看是否可以在查詢運行後將其刷新或使其中的某些查詢無效,以便您在其餘時間獲得好處。 –

+0

你有沒有這樣的運氣? –