Hibernate查询缓存驱逐策略

时间:2010-11-17 02:47:10

标签: java hibernate caching orm jpa

对于一个简单的Post-Tag @ManyToMany场景,例如@ManyToMany inconsistent data on both side problem

似乎hibernate的二级缓存不知道更新聚合函数的时间(ex:count),如下所示:

public int getPostCountByTag(Tag tag)
{
  Session session = (Session) em.getDelegate();
  Criteria c = session.createCriteria(Post.class);

  c.createCriteria("tags")
  .add(Restrictions.eq("id", tag.getId()));

  c.setProjection(Projections.rowCount());
  c.setCacheable(true);
  int num = ((Long) c.uniqueResult()).intValue();
  return num;
}

hibernate也不知道是时候更新像这样的列表了:

public List<Post> getPostsByTag(Tag tag, int start, int count)
{
  Session session = (Session) em.getDelegate();
  Criteria c = session.createCriteria(Post.class);

  c.createCriteria("tags")
   .add(Restrictions.eq("id", tag.getId()));

  c.addOrder(Order.desc("created")); break;
  c.setFirstResult(start);
  c.setMaxResults(count);
  c.setCacheable(true);

  return c.list();
}

每次我在帖子中添加/删除标签时,这些计数和列表都保持不变。我知道也许是因为它们被c.setCacheable(true)缓存了,我必须手动逐出缓存或将超时设置得更短。

但是,我想知道是否有更好/更聪明的方式让hibernate自动检测缓存逐出时间?

在该示例中,只有两种方法受标记的添加/删除影响,但随着方法的增长,缓存逐出管理将变得非常麻烦且容易出错。例如:

addTag(Post post , Tag tag)
{
  post.addTag(tag);
  postDao.update(post);
  EntityManagerFactoryUtils.getTransactionalEntityManager(emf).flush();

  evict_cache_in_getPostsByTag();
  evict_cache_in_getPostCountByTag();
  evict_cache_in_getPostsByTagAndBlah();
  evict_cache_in_getPostsByTagAndBlahBlah();
  evict_cache_in_getPostsByTagAndBlahBlahBlah();
}

removeTag(Post post , Tag tag)
{
  post.removeTag(tag);
  postDao.update(post);
  EntityManagerFactoryUtils.getTransactionalEntityManager(emf).flush();

  evict_cache_in_getPostsByTag();
  evict_cache_in_getPostCountByTag();
  evict_cache_in_getPostsByTagAndBlah();
  evict_cache_in_getPostsByTagAndBlahBlah();
  evict_cache_in_getPostsByTagAndBlahBlahBlah();
}

这太糟糕了!!!

我想知道如何解决这个n x m问题? (n为2 (add/remove),m为5 (evicts),在此示例中)

顺便说一下,我发现hibernate的cache.evictQueryRegions()似乎根本不起作用。我必须手动为每个查询缓存命名(缓存区域),并指定要由cache.evictQueryRegion("getTagPostsCount");驱逐的缓存区域,我是否遗漏了什么?还是Hibernate的bug? (更新:升级到Hibernate 3.6.0.Final之后,问题解决了,似乎是3.5.6的bug)

Hibernate 3.5.6-Final,hibernate-jpa-2.0,ehcache-1.5.0,Spring-3.0.4

1 个答案:

答案 0 :(得分:0)

已将hibernate配置为使用二级缓存,就像使用ehcache实现l2缓存一样。因为如果您正在使用它,那么您可以添加从数据库更新缓存的时间(与数据库同步),

这是我在我的申请中使用的,可能这可以帮助你..

<defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true"/>

在过期时间后,缓存将自动更新。