2010-11-17 134 views
0

对于简单的后标签@ManyToMany场景像这样的@ManyToMany inconsistent data on both side problemHibernate查询缓存驱逐策略

看来,Hibernate的二级缓存并不知道更新聚合函数时(例如:计数)像这样之一:

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),我必须手动驱逐缓存或者缩短超时时间。

但是,我不知道是否有任何更好/更聪明的方式来休眠自动检测缓存驱逐时间?

在这个例子中,只有两个方法受到标签添加/删除的影响,但随着方法的增长,缓存驱逐管理将变得非常繁琐且容易出错。例如:

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

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

这是我在我的应用程序中使用的,可能是这可以帮助你..

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

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