如何使用Spring清除所有的Hibernate缓存(ehcache)?

30

我正在使用第二级缓存和查询缓存。请问如何以编程方式清除所有缓存?

7个回答

38

根据Hibernate JavaDoc,Bozho答案中指示的代码片段已经在Hibernate 4中被弃用。

您可以使用org.hibernate.Cache.evictAllRegions()

从所有查询区域清除数据。

使用API:

Session session = sessionFactory.getCurrentSession();

if (session != null) {
    session.clear(); // internal cache clear
}

Cache cache = sessionFactory.getCache();

if (cache != null) {
    cache.evictAllRegions(); // Evict data from all query regions.
}

或者,您可以清除特定范围的所有数据:

org.hibernate.Cache.evictCollectionRegions()
org.hibernate.Cache.evictDefaultQueryRegion()
org.hibernate.Cache.evictEntityRegions()
org.hibernate.Cache.evictQueryRegions()
org.hibernate.Cache.evictNaturalIdRegions()

您可能希望查看 Hibernate缓存接口的JavaDoc(Hibernate 4.3)

此外,还可以查看 Hibernate开发指南(4.3) 中关于二级缓存淘汰的介绍


我想通过调用以下方法从二级缓存中清除缓存数据:-sessionFactory.getCache().evictEntityRegions();我只是想知道,这样做会有什么危害吗?例如:如果我尝试在事务进行中清除缓存,会发生什么? - Vikas Sharma
1
我猜这取决于你的缓存策略和提供商。你可能需要用所选的进行测试。参考文档描述了不同的设置。 - Dino
我正在使用@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)。 我有一个情况。假设在运行某些事务以从中获取数据时,第二级缓存具有数据。同时,另一个线程清除了所有区域缓存,而前一个事务尚未完成。那么在这种情况下会发生什么?在该事务中,我能否从缓存中获取null并发生db hit?是否存在任何问题的可能性? - Vikas Sharma
你应该根据你的具体环境编写一个测试。根据文档,读写似乎符合你的情况,但请注意它有要求,在这里都有详细说明(参考 https://docs.jboss.org/hibernate/orm/4.3/devguide/en-US/html/ch06.html#caching-strategies-list)。 - Dino

17

清除会话缓存使用session.clear()

清除二级缓存使用此代码片段


7
对于现代版本的Hibernate,最好遵循@dino的答案。 - King Midas

3
如果您安装了Terracotta,您还可以运行Terracotta Dev Console。该工具可以检查有关缓存的统计信息,打开和关闭缓存,并从用户界面清除缓存内容。此功能也可通过JMX bean使用。

2

@Dino的回答对我来说几乎有效,但是我从sessionFactory.getCurrentSession()得到了一个错误(未配置当前会话上下文!)。 我发现这对我有用:


sessionFactory.openSession()

最初的回答。

    // Use @Autowired EntityManager em
    em.getEntityManagerFactory().getCache().evictAll();

    // All of the following require org.hibernate imports
    Session session = em.unwrap(Session.class);

    if (session != null) {
        session.clear(); // internal cache clear
    }

    SessionFactory sessionFactory = em.getEntityManagerFactory().unwrap(SessionFactory.class);

    Cache cache = sessionFactory.getCache();

    if (cache != null) {
        cache.evictAllRegions(); // Evict data from all query regions.
    }

1

与 @Dino 的答案相同,JPA 2.0 API 的简化语法:

@Autowired
private EntityManagerFactory entityManagerFactory;

public void clearHibernateCaches() {
    entityManagerFactory.getCache().unwrap(org.hibernate.Cache.class).evictAllRegions();
}

0

如果您想清除二级缓存,请使用API sessionFactory.evictEntity(entityName)

代码:

/**
 * Evicts all second level cache hibernate entites. This is generally only
 * needed when an external application modifies the database.
 */
public void evict2ndLevelCache() {
    try {
        Map<String, ClassMetadata> classesMetadata = sessionFactory.getAllClassMetadata();
        for (String entityName : classesMetadata.keySet()) {
            logger.info("Evicting Entity from 2nd level cache: " + entityName);
            sessionFactory.evictEntity(entityName);
        }
    } catch (Exception e) {
        logger.logp(Level.SEVERE, "SessionController", "evict2ndLevelCache", "Error evicting 2nd level hibernate cache entities: ", e);
    }
}

关于二级缓存的更多细节请参阅


-13

你也可以选择这个

request.getSession().invalidate();      
        response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); 
        response.setHeader("Pragma", "no-cache");
        response.setDateHeader("Expires", 0);

9
HttpSession 和 Hibernate session 是不同的东西。 - Sachin Verma

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接