【问题标题】:Preloaded Ehcache Ignored when using @Cacheable Annotation使用 @Cacheable 注解时忽略预加载的 Ehcache
【发布时间】:2014-02-20 12:54:39
【问题描述】:

我还是 ehcache API 的新手,所以我可能会遗漏一些明显的东西,但这是我当前的问题。

我目前有一个永久磁盘缓存存储在我的服务器上。我目前正在实现一种被动的后写缓存方法,它将键/值对保存到数据库表中。如果永久磁盘缓存丢失,我想从数据库表中恢复缓存。

我用于后写逻辑的示例:

http://scalejava.blogspot.com/2011/10/ehcache-write-behind-example.html

我正在使用以下方法构建磁盘持久性:

import com.googlecode.ehcache.annotations.Cacheable;
import com.googlecode.ehcache.annotations.KeyGenerator;
import com.googlecode.ehcache.annotations.PartialCacheKey;

@Cacheable(cacheName = "readRuleCache", keyGenerator=@KeyGenerator(name="StringCacheKeyGenerator"))
public Rule read(@PartialCacheKey Rule rule,String info) {        

    System.out.print("Cache miss: "+ rule.toString());

    //code to manipulate Rule object using info

    try{
        String serialziedRule =objectSerializer.convertToString(Rule);
        readRuleCache.putWithWriter(new Element(rule.toString(),serialziedRule ));
    }
    catch(IOException ioe)
    {
        System.out.println("error serializing rule object");
        ioe.printStackTrace();
    }

    return rule;
}

我在 CacheWriter 实现中重写的 write 方法工作正常。事情正在被保存到数据库中。

 @Override
 public void write(final Element element) throws CacheException {

    String insertKeyValuePair ="INSERT INTO RULE_CACHE (ID, VALUE)  VALUES " +
            "('"+element.getObjectKey().toString()+"','"
                +element.getObjectValue().toString()+"')";

    Statement statement;
        try 
{
        statement = connection.createStatement();
        statement.executeUpdate(insertKeyValuePair);
        statement.close();

    } catch (SQLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

查询字符串并将其反序列化回对象也可以正常工作。我已经验证了该对象的所有值都存在。当我删除 *.data 文件并重新启动应用程序时,磁盘持久缓存也会被填充:

public void preLoadCache()
{
   CacheManager cacheManager = CacheManager.getInstance();

    readRuleCache = cacheManager.getCache("readRuleCache");

    Query query=em.createNativeQuery("select * from RULE_CACHE");

     @SuppressWarnings("unchecked")
     List<Object[]> resultList = query.getResultList();

     for(Object[] row:resultList)
     {

        try {

            System.out.println("Deserializing: "+row[1].toString());
            Rule rule = objectSerializer.convertToObject((String)row[1]);
            rule= RuleValidator.verify(rule);
             if(rule!=null)
             {
               readAirRuleCache.putIfAbsent(new Element(row[0], rule));

             }
        } 
        catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
     }
}

问题

一切看起来都不错。但是,当我使用应该存在于缓存中的键传递 Rule 对象时,无论如何都会调用“读取”方法并且 *.data 文件大小会增加。尽管数据库的 write 方法不会尝试再次插入现有的键。关于我做错了什么的任何想法?

【问题讨论】:

    标签: java spring ehcache spring-cache


    【解决方案1】:

    原来这是罪魁祸首:

    keyGenerator=@KeyGenerator(name="StringCacheKeyGenerator")       
    

    我阅读的源材料表明,我覆盖的“toString()”方法将用作缓存键/值对的键。经过进一步研究,事实证明这是不正确的。虽然使用了“toString()”键。它嵌套在类信息中以创建更大的键。

    参考:

    http://code.google.com/p/ehcache-spring-annotations/wiki/StringCacheKeyGenerator

    示例预期键: “[49931]”

    示例实际键: "[class x.y.z.WeatherDaoImpl, getWeather class x.y.z.Weather, [class java.lang.String], [49931]]"

    【讨论】:

      猜你喜欢
      • 2018-07-03
      • 2012-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-19
      • 2019-02-18
      • 2019-11-26
      • 1970-01-01
      相关资源
      最近更新 更多