3

我还是 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 方法不会尝试再次插入现有的键。关于我做错了什么的任何想法?

4

1 回答 1

1

原来这是罪魁祸首:

keyGenerator=@KeyGenerator(name="StringCacheKeyGenerator")       

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

参考:

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

示例 预期键:“[49931]”

示例实际键:“[class xyzWeatherDaoImpl, getWeather class xyzWeather, [class java.lang.String], [49931]]”

于 2014-02-06T07:15:47.877 回答