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