2012-01-30 90 views
1

我需要在servlet啓動時從數據庫「預加載」一些數據。Java緩存和動態更新

所以我想創建一些緩存,例如使用HashMap或某些類似的同步版本。

我還需要更新數據庫更新更改的緩存。
所以我想添加某種「聽衆」。

我的問題是:這是某種方式可用或我必須實際執行它?

如果是,什麼樣的設計模式是最好的方法?

更新:
沒有使用JPA或ORM。但春天有售

+0

您是否使用圖書館進行持久性?它們中的大多數已經支持各種形式的緩存,不需要重新發明輪子。 – Affe 2012-01-30 18:41:50

+0

No.Direct SQL調用數據庫 – Cratylus 2012-01-30 18:42:26

+0

您的緩存是否需要分發到多個進程?寫操作是否需要更新其他緩存實例(或導致它們更新),還是隻與正在寫入的進程相關? – philwb 2012-01-30 22:13:07

回答

2

您可能在這裏找到您需要的最好的Guava。 Caches上的wiki article可能與您最相關,但這裏的確切方法在很大程度上取決於數據庫更新更改的條件。如果要在數據庫更新更改時刷新整個緩存 - 或者至少使舊條目無效 - 則只要發生數據庫更新,就可以撥打Cache.invalidateAll()。如果您願意讓緩存稍微落後於時間,那麼使用CacheBuilder.refreshAfterWrite(long, TimeUnit)可能對您很有幫助。

+0

@LuisWasserman:我從來沒有使用番石榴before.Is它只是1罐還是有很多依賴我問,因爲該項目是相當small.I不能存在於例如?由於依賴關係到其他庫需要20 MB – Cratylus 2012-01-30 18:45:08

+0

我相信它最多隻有一個依賴項,即(小)JSR-305。這可能不是絕對必要的。如果你關心輸出JAR的大小,我們推薦http://proguard.sourceforge.net/。 – 2012-01-30 18:49:37

+0

這是一種低複雜度的方法,可滿足您的需求,並且是開始的好地方。 – philwb 2012-01-31 16:45:07

0

散列圖及其線程安全變體ConcurrentHashMap已經可用。

有一些緩存解決方案可以像ehcache一樣提供高級支持,如驅逐策略等等。

至於設計模式,讀入Observer設計模式。

0

我實際上有一個生產級別的項目,我需要做這樣的事情。我的解決方案是(這只是我的解決方案)是在servlet啓動時將對象(您的「數據」)加載到內存中。做出這個決定是因爲該對象足夠大,導致客戶端請求緩慢地將其從數據庫中拉出來,並且我有少量的併發用戶。任何會改變數據庫中對象數據的請求也會改變內存中的對象。如果您與很多用戶合作,您當然需要使用同步對象來完成此操作。如果數據量不是很大,那麼每當用戶請求有關數據的信息時,都可以從數據庫中提取數據。

祝你好運。

3

是當然的,您可以實現
我會畫一個小的架構,然後生病解釋給U:

Architecture diagram

首先,你可以瞭解映射器here和TDGS here。 映射程序有一個方法,稱爲cacheAll()它調用並委託到TDG的方法cacheAll()它的任務是從數據庫中獲取表中的所有行(您要緩存的行緩存對象)。

所以基本上你首先必須創建實施「的ServletContextListener」 這意味着它的整個servlet上下文監聽器監聽器,並且其內部contextInitialized你必須調用mp.fill(Mapper.cacheAll( )),所以它STHG像(這是一般的代碼,當然最好是寫和優化)

public class myServletContextListener implements ServletContextListener{ 

@Override 
public void contextInitialized(ServletContextEvent sce) { 
     mp.fill(Mapper.cacheAll()); 
} 

// 
} 

不要忘記添加監聽器在web.xml:

<listener> 
    <listener-class>myServletContextListener </listener-class> 
</listener> 

所以這樣做會在服務器啓動時將所有記錄緩存到緩存對象中的hashmap mp中。

至於基於數據庫更改更新緩存,您將不得不使用observer pattern

UPDATE
我忘了提,關於緩存對象,我想你想爲所有用戶或您的應用程序訪問,所以你應該把它作爲一個singleton(單例模式),這樣的代碼的代碼:

public class cacheObject 
{ 
    private static Map cMap; 
    private static cacheObject cObject; 
    private cacheObject() 
    { 
     cMap = Mapper.cacheAll(); 
    } 
    public static synchronized cacheObject getInstance() 
    { 
     if (cObject == null){ 
      cObject = new cacheObject(); 
     } 
     return cObject; 
    } 

} 

此外,如果你希望緩存可以數據由用戶更改,所以使它成爲一個ThreadLocal的單。