在他的优秀博客文章“Hibernate query cache considered harmful?”中,亚力士米勒(Terracotta Inc.)解释了为什么使用查询缓存会对延迟和可扩展性造成损害。
我的问题是:是否有可能为使用二级缓存而没有查询缓存的特定域对象类型编写“get all”DAO方法?
我这种方法的常用代码形式涉及查询缓存,例如:
public List<Foo> getAllFoo()
{
return (List<Foo>) getHibernateTemplate().execute(new HibernateCallback()
{
public Object doInHibernate(Session session)
{
Query q = session.createQuery("from Foo");
// Cache the results in the query cache.
q.setCacheable(true);
return q.list();
}
});
}
我唯一模糊的想法是在一些单例域对象(也被缓存)上维护所有Foo的缓存集合。有更优雅的方式吗?
答案 0 :(得分:1)
如果您正在使用EhCacheProvider,您需要的是访问CacheManager成员变量。不幸的是,它是私有的,没有公共访问方法,所以我最终创建了自己的EhCacheProvider副本,它使用静态的CacheManager和一个公共静态方法来返回它。我假设您可以以相同的方式处理其他缓存提供程序,或者只是实现CacheProvider接口。
拥有CacheManager后,您将使用cacheManager.getCache(类名)获取域(类)名称的缓存。返回一个Cache,您可以使用cache.getKeys()进行迭代。每个键都是一个CacheKey,它上面有实体id,因此您可以使用cache.get(key)返回实际实体。
如果您不介意绕过某些Java安全性并依赖于特定的Hibernate实现,那么另一种选择是(省略异常处理):
EhCacheProvider cp = (EhCacheProvider)((SessionFactoryImpl)session.getSessionFactory()).getSettings().getCacheProvider()
Field f = EhCacheProvider.class.getDeclaredField("manager");
f.setAccessible(true);
CacheManager cm = (CacheManager)f.get(cp);
Cache c = cm.get(Entity.class);