从没有查询缓存的Hibernate二级缓存中检索所有Foo?

时间:2009-08-19 19:00:54

标签: hibernate

在他的优秀博客文章“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的缓存集合。有更优雅的方式吗?

1 个答案:

答案 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);