2016-12-23 10 views
1

キャッシングをEhCacheで実装する必要があります。基本的な要件は、キャッシュされたオブジェクトを一定間隔(以下のコードでは1時間)の間保持する必要があります。だから、私は以下のようにコードを実装:EhCacheキャッシュオブジェクトの修正

サンプルドメインオブジェクト:

import lombok.*; 
@Getter 
@Setter 
@ToString 
@AllArgsConstructor 
public class City implements Serializable { 
    public String name; 
    public String country; 
    public int population; 
} 

キャッシュマネージャクラス:

import net.sf.ehcache.*; 
public class JsonObjCacheManager { 
    private static final Logger logger = LoggerFactory.getLogger(JsonObjCacheManager.class); 
    private CacheManager manager; 

    private Cache objectCache; 

    public JsonObjCacheManager(){ 
     manager = CacheManager.create(); 

     objectCache = manager.getCache("jsonDocCache"); 

     if(objectCache == null){ 
      objectCache = new Cache(
        new CacheConfiguration("jsonDocCache", 1000) 
          .memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LRU) 
          .eternal(false) 
          .timeToLiveSeconds(60 * 60) 
          .timeToIdleSeconds(0) 
          .diskExpiryThreadIntervalSeconds(0) 
          .persistence(new PersistenceConfiguration().strategy(PersistenceConfiguration.Strategy.LOCALTEMPSWAP))); 
      objectCache.disableDynamicFeatures(); 
      manager.addCache(objectCache); 
     } 
    } 

    public List<String> getKeys() { return objectCache.getKeys();} 

    public void clearCache(){ 
     manager.removeAllCaches(); 
    } 

    public void putInCache(String key, Object value){ 
     try{ 
      objectCache.put(new Element(key, value)); 
     }catch (CacheException e){ 
      logger.error(String.format("Problem occurred while putting data into cache: %s", e.getMessage())); 
     } 
    } 

    public Object retrieveFromCache(String key){ 
     try { 
      Element element = objectCache.get(key); 
      if(element != null) 
       return element.getObjectValue(); 
     }catch (CacheException ce){ 
      logger.error(String.format("Problem occurred while trying to retrieveSpecific from cache: %s", ce.getMessage())); 
     } 
     return null; 
    } 
} 

をそれは非常に適切な値をキャッシュして取得します。しかし、私の必要条件は、私は指定されたキーのキャッシュから取得するオブジェクトを変更する必要があります。私が得ているのは、キャッシュから取得したオブジェクトを変更すると、そのキーのキャッシュオブジェクトも変更されていることです。以下は

例です。

public class Application { 

     public static void main(String[] args) { 
      JsonObjCacheManager manager = new JsonObjCacheManager(); 

      final City city1 = new City("ATL","USA",12100); 
      final City city2 = new City("FL","USA",12000); 

      manager.putInCache(city1.getName(), city1); 
      manager.putInCache(city2.getName(), city2); 

      System.out.println(manager.getKeys()); 

      for(String key: manager.getKeys()){ 
       System.out.println(key + ": "+ manager.retrieveFromCache(key)); 
      } 

      City cityFromCache = (City) manager.retrieveFromCache(city1.getName()); 
      cityFromCache.setName("KTM"); 
      cityFromCache.setCountry("NPL"); 
      System.out.println(manager.getKeys()); 

      for(String key: manager.getKeys()){ 
       System.out.println(key + ": "+ manager.retrieveFromCache(key)); 
      } 
     } 
} 

私は取得しています出力は次のようになります。

[ATL, FL] 
ATL: City(name=ATL, country=USA, population=12100) 
FL: City(name=FL, country=USA, population=12000) 
[ATL, FL] 
ATL: City(name=KTM, country=NPL, population=12100) 
FL: City(name=FL, country=USA, population=12000) 

私はそれはまた、指定されたキーのオブジェクトを取得し、修正していたときにこれは、意味キャッシュされた値に反映されます。

私の要件は、指定されたキーのキャッシュオブジェクトは変更しないでください。これを達成する方法はありますか?それとも、EhCacheを実装する正しい方法ではありませんか?それとも基本的な原則が欠けているのですか?私はEhcacheののV2.10.3を使用してい

ありがとうございました!

答えて

2

データをヒープに格納しているキャッシュと直接オブジェクト参照を使用する場合は、そのオブジェクトを使用する前にコピーする必要があります。

一般に、オブジェクト参照をキャッシュに渡した後で値を変更しないことをお勧めします(または制御できないもの)。

キャッシュの中には、キャッシュされた値を変更から保護するためのコピーメカニズムがあります。例えば。 EHCache3では複写機を追加できます。Serializers and Copiersを参照してください。

また、値を変更する必要がある場合は、値を2つのオブジェクトに分割することもできます.1つはキャッシュ、もう1つは変更が必要なデータを格納し、後者には最初の。

+0

@cruftexありがとうございます。それは多くの助けになります。私はシリアライザーと複写機を試し、それが私のために働くかどうかを知らせます。 :) –

+0

ワウ,,,,複写機は私のために良い仕事をするつもりです:) @クルーファックス –

+0

それは複写機が何かを使用している深いクローンですか?私はEhCahce3 Docsでこれについて何の言及も見つけられませんでした。ありがとう。 –