2014-05-22 36 views
0

我在這裏虧本。番石榴CacheLoader錯過

我已經真的很幸運,手動加載/插入Guava緩存,但我決定它應該更「線程安全」(通過CacheLoader)。

當我重構爲使用CacheLoader.load樣式語法時,我的緩存停止工作。每個get()現在都是一個緩存缺失,並開始調用load()。

我錯過了一些非常簡單的東西嗎?

緩存:

public class DatabasePropertyCache implements RemovalListener<DatabasePropertyCache.Key, Optional<Object>> { 

    //InitializeOnDemand style singleton 
    // http://en.wikipedia.org/wiki/Singleton_pattern#Initialization_On_Demand_Holder_Idiom 
    private static class Singleton { 
     static DatabasePropertyCache INSTANCE = new DatabasePropertyCache(); 
    } 
    public static DatabasePropertyCache getInstance() { 
     return Singleton.INSTANCE; 
    } 
    private DatabasePropertyCache() { 
     logger = Logger.getLogger(DatabasePropertyCache.class); 
     cache = CacheBuilder 
        .newBuilder() 
        .expireAfterWrite(24, TimeUnit.HOURS) 
        .removalListener(this) 
        .build( 
         new CacheLoader<Key, Optional<Object>>() { 

          @Override 
          public Optional<Object> load(Key key) throws Exception { 
           Object propertyValue = [performs a query] 
           return Optional.fromNullable(propertyValue); 
          } 
         }); 
    } 

    private final LoadingCache<Key, Optional<Object>> cache; 
    private final Logger logger; 

    public void onRemoval(RemovalNotification<Key, Optional<Object>> arg0) { 
     if(logger.isDebugEnabled()) { 
      logger.debug(String.format("Cached database property expiring %s", arg0.getKey().toString())); 
     } 
    } 

    /** 
    * Returns a cached value. If it has never been cache before, it will be fetched from the database. 
    * 
    * @param value 
    * @param locale 
    * @param dataset 
    * @return 
    */ 
    public Object getObject(String id, DatabasePropertiesEnum property, Locale locale) { 
     Key key = new Key(id, property, locale); 

     try { 
      return cache.get(key).orNull(); 
     } 
     catch (ExecutionException eex) { 
      logger.warn(String.format("Error fetching database property %s", key.toString()), eex); 
     } 
     return null; 
    } 

    protected class Key { 

     private static final String TOSTRING_TEMPLATE = "DatabasePropertyCache.Key[dataset=%s, locale=%s, property=%s]"; 

     private String id; 
     private DatabasePropertiesEnum property; 
     private Locale locale; 

     public Key(String id, DatabasePropertiesEnum property, Locale locale) { 
      this.id= id; 
      this.property = property; 
      this.locale = locale; 
     } 

     @Override 
     public int hashCode() { 
      return new HashCodeBuilder() 
        .append(this.id) 
        .append(this.property) 
        .append(this.locale) 
        .toHashCode(); 
     } 

     public String getId() { 
      return id; 
     } 

     public DatabasePropertiesEnum getProperty() { 
      return property; 
     } 

     public Locale getLocale() { 
      return locale; 
     } 

     @Override 
     public String toString() { 
      return String.format(TOSTRING_TEMPLATE, id, locale.toString(), property.name()); 
     } 
    } 
} 

用法:

Object cacheHit = DatabasePropertyCache.getInstance().getObject("some_id", DatabasePropertiesEnum.SOME_KEY, [users current locale]); 

回答

3

Key類必須正確實施equals()hashcode()

您可以使用Guava EqualsTester來測試你的equals和hashCode:

2

它看起來像你的Key類需要定義一個equals()方法。

+0

所以,是的,我失去了一些東西真的很簡單。我們以前的實現使用int(通過.hashCode())作爲鍵,因此是錯誤。謝謝! –