对于一个简单的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
答案 0 :(得分:0)
已将hibernate配置为使用二级缓存,就像使用ehcache实现l2缓存一样。因为如果您正在使用它,那么您可以添加从数据库更新缓存的时间(与数据库同步),
这是我在我的申请中使用的,可能这可以帮助你..
<defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true"/>
在过期时间后,缓存将自动更新。