2012-01-30 17 views
1

サーブレットの起動時にデータベースからデータを「プリロード」する必要があります。Javaキャッシュと動的に更新

私はいくつかのキャッシュを作成すると考えました。 HashMapまたは類似の同期バージョンを使用します。

また、データベースの更新時にキャッシュを更新する必要があります。
だから私はある種の「リスナー」を追加すると考えました。

私の質問です:これは何とか利用できますか、それとも実際に実装する必要がありますか?

もしそうなら、どんなデザインパターンが最良の方法でしょうか?

更新:
JPAまたはORMは使用されません。しかし、春は利用可能です

+0

あなたは永続性のためにライブラリを使用していますか?それらの大部分はすでにさまざまな形のキャッシュをサポートしており、ホイールを再構築する必要はありません。 – Affe

+0

いいえ。データベースへの直接SQL呼び出し – Cratylus

+0

キャッシュを複数のプロセスに配布する必要がありますか?書き込み操作は、他のキャッシュ・インスタンスを更新する必要がありますか(または更新させるか)、書き込みを行っているプロセスにのみ関連していますか? – philwb

答えて

2

あなたのニーズはGuavaで最もよく役立つことがあります。キャッシュ上のwiki articleがおそらく最も関連性がありますが、ここでの正確なアプローチは、データベースの更新の変更条件に大きく依存します。データベース更新の変更でキャッシュ全体をリフレッシュしたい場合や、少なくとも古いエントリを無効にする場合は、データベースの更新が発生するたびにCache.invalidateAll()を呼び出すだけです。キャッシュを少し遅れさせたい場合は、CacheBuilder.refreshAfterWrite(long, TimeUnit)を使用するとうまくいくでしょう。

+0

@LuisWasserman:私はGuavaを使用したことがありません.1つだけのjarか、それとも多くの依存関係がありますか?プロジェクトはかなり小さいので質問します。他のライブラリとの依存関係のために20 MBの余裕がある – Cratylus

+0

JSR-305には1つの依存関係があると思います。それは厳密に必要ではないかもしれません。出力JARサイズが気になる場合は、http://proguard.sourceforge.net/をお勧めします。 –

+0

これはあなたのニーズに合った、複雑さの低い手法であり、開始するのに適しています。 – philwb

0

ハッシュマップとスレッドセーフなバリアントです。ConcurrentHashMapはすでに利用可能です。

ehcacheのように利用可能なキャッシングソリューションがあります。このソリューションは、エビクションポリシーなどの高度なサポートも提供しています。

デザインパターンは、オブザーバーデザインパターンを参照してください。

0

私は実際にこのようなことをする必要があるプロダクションレベルのプロジェクトを持っていました。私の解決策は(これはちょうど私の解決策です)サーブレットの起動時にオブジェクト(あなたの "データ")をメモリにロードすることでした。この決定は、オブジェクトのサイズが十分に大きいためにクライアントの要求がデータベースから取り出すのが遅くなり、少数の同時ユーザーが発生したために行われました。データベース内のそのオブジェクトのデータを変更する要求もメモリ内オブジェクトを変更します。もちろん、多くのユーザーと作業している場合は、同期オブジェクトを使用してこれを行う必要があります。データの量が膨大でない場合は、ユーザーがデータに関する情報を要求するたびに、常にデータベースから引き出すことができます。

Good Luck。あなたが実装することができ

3

もちろんはい
私は病気その後、小さなアーキテクチャを描きますが、Uにそれを説明すること:すべての

Architecture diagram

まず、あなたはマッパーhereとTDGS hereについて学ぶことができます。 マッパーにはというcacheAll()というメソッドがあり、これはTDGのメソッドを呼び出してデリゲートします。cacheAll()これはdbのテーブルからすべての行を取得するという使命を持っています。キャッシュオブジェクト)。

ので、基本的には、第1あなたがそのに全体のサーブレットコンテキストのリスナーを意味「のServletContextListener」 を実装するリスナーを作成する必要があり、そのの内側にあなたがmp.fill(Mapper.cacheAllを(呼び出す必要がありをcontextInitialized ))、それは同じよう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> 

これは、サーバーの起動時に、キャッシュオブジェクト内のすべてのレコードをハッシュマップmpにキャッシュします。

データベースの変更に基づいてキャッシュを更新する場合は、observer patternを使用する必要があります。

UPDATE
私はキャッシュオブジェクトについて、言及するのを忘れて、私はあなたがすべてのユーザーまたはあなたのアプリ用にアクセスしたいと仮定し、あなたがそのようなシングルトン(シングルトンパターン)、コードとしてそれをコーディングする必要があります:

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シングルトン作ることができます。

関連する問題