2008-09-07 19 views
7

我們的設計有一個jvm,它是一個jboss/webapp(讀/寫),用於通過休眠(使用jpa)來維護數據到數據庫。該模型具有10-15個持久類,關係中有3-5個深度級別。如何維護運行兩個Java應用程序的Hibernate緩存一致性?

然後,我們有一個單獨的jvm,即使用此數據的服務器。當它連續運行時,我們只有一個長數據庫會話(只讀)。

目前沒有涉及到jvm內部的緩存 - 所以我們手動向另一個jvm發送信號。

現在,當web應用程序改變一些數據時,它會通知服務器重新加載更改的數據。我們發現,我們需要告訴休眠來清除數據,然後重新加載它。只是在數據庫中執行讀取/合併操作並不能完成這項工作 - 主要是關於層次結構下幾層的對象。

任何關於這個設計是否存在根本性錯誤的想法,或者是否有人這樣做,並且在重新加載時使用hibernate獲得更好的運氣。

謝謝, 克里斯

回答

10

Hibernate會話將從DB讀取的所有數據加載到他們稱爲的第一級高速緩存。一旦從DB加載一行,任何後續的具有相同PK的行的獲取都將從此緩存中返回數據。此外,Hibernate gaurentees在單個Session中引用具有相同PK的對象的平等。

據我所知,你的只讀服務器應用程序永遠不會關閉它的Hibernate會話。因此,當讀寫應用程序更新數據庫時,只讀服務器上的Session不知道更改。實際上,您的只讀應用程序正在加載數據庫的內存副本並使用該副本,並在適當的時候過期。

我可以建議的最簡單和最好的方法是根據需要關閉並打開會話。這回避了整個問題。休眠會話旨在成爲與數據庫進行短暫交互的窗口。我同意不會一次又一次地重新載入對象圖,這會帶來性能上的提升。但你需要衡量它並說服自己,這是值得的痛苦。

另一種選擇是定期關閉並重新打開會話。這確保了只讀應用程序可以處理不超過給定時間間隔的數據。但是肯定有一個窗口,只讀應用程序使用陳舊的數據(儘管設計保證它最終獲得最新的數據)。這在許多應用中可能是允許的 - 您需要評估您的情況。

第三個選項是使用二級緩存實現,並使用短暫的Sessions。有各種緩存包與Hibernate一起工作,具有相對的優點和缺點。

+0

使用JPA和@PersistenceContext獲取EntityManager的 - 但似乎我們需要@PersistenceUnit一個EntityManagerFactory接口和刷新數據,我們得到了一個新的EntityManager。聽起來很不錯 - 但是如果人們更新的東西很多,但是如果那是人們做的事情...... – 2008-09-10 13:50:27

3

克里斯,我有點困惑你的情況。如果我理解正確,那麼您有兩個Web應用程序(讀/寫)使用Hibernate訪問共享數據庫的獨立應用程序(只讀?)。您使用網絡應用程序所做的更改對獨立應用程序不可見。是對的嗎?

如果是這樣,你有沒有考慮過使用不同的二級緩存實現?我想知道您是否可以使用Web應用程序和獨立應用程序共享的羣集緩存。我相信與Hibernate集成的SwarmCache將允許這樣做,但我沒有嘗試過。

一般來說,您應該知道給定緩存的內容永遠不會知道其他應用程序的活動(這就是爲什麼我建議讓這兩個應用程序共享一個緩存)。祝你好運!

2

從我的角度來看,您應該將您的下劃線Hibernate緩存更改爲支持羣集模式的緩存。它可能是JBoss CacheSwarm Cache。第一個更好地支持數據同步(複製和失效),並支持JTA。

然後,您將能夠配置webapp和服務器之間的緩存同步。如果您使用JBoss Cache,那麼還要查看隔離級別。我相信你應該使用READ_COMMITTED模式,如果你想從同一個會話獲取服務器上的新數據。

1

最常用的做法是有一個Container-Managed Entity Manager,以便同一個容器(即Glassfish,Tomcat,Websphere)中的兩個或多個應用程序可以共享相同的緩存。 但是,如果您不使用應用程序容器,因爲您使用Play!例如,那麼我會在主要應用程序中構建一些Web服務以在緩存中一致地讀/寫。

我認爲使用陳舊的數據是一場災難。就像Singletons變成Multitons一樣,只讀應用程序通常是,有時寫爲

帶和揹帶 :)

相關問題