2014-05-22 38 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())作为键,因此是错误。谢谢! –