首页 文章

使用@Cacheable Annotation时忽略预加载的Ehcache

提问于
浏览
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();
        }
     }
}

Question

一切都很好看 . 但是,当我传递带有应存在于缓存中的键的Rule对象时,无论如何都会调用“read”方法,并且* .data文件大小会增加 . 虽然数据库的write方法不会尝试再次插入现有密钥 . 关于我做错了什么的任何想法?

1 回答

  • 1

    事实证明这是罪魁祸首:

    keyGenerator=@KeyGenerator(name="StringCacheKeyGenerator")
    

    我读到的源材料表明我覆盖的“toString()”方法将被用作缓存键/值对的键 . 经过进一步研究后发现事实并非如此 . 虽然使用了“toString()”键 . 它嵌套在类信息中以创建更大的密钥 .

    参考:

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

    示例预期密钥:“[49931]”

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

相关问题