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

Posted

技术标签:

【中文标题】如何使用 Spring 清除所有 Hibernate 缓存(ehcache)?【英文标题】:How to clear all Hibernate cache (ehcache) using Spring? 【发布时间】:2010-03-17 09:31:12 【问题描述】:

我正在使用二级缓存和查询缓存。 我可以知道如何以编程方式清除所有缓存吗?

【问题讨论】:

【参考方案1】:

Bozho 答案中指示的代码 sn-p 在 Hibernate 4 中已弃用。

根据Hibernate JavaDoc,可以使用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()

您可能想查看the JavaDoc for hibernate Cache interface (Hibernate 4.3)。

另外,second-level cache eviction 来自休眠开发指南 (4.3)。

【讨论】:

我想通过调用以下方法从二级缓存中清除缓存数据:- sessionFactory.getCache().evictEntityRegions();我只想知道,这样做有什么坏处吗?例如:- 如果我尝试在事务中间清除缓存会发生什么? 我想这取决于您的缓存策略和提供者。您可能需要使用所选的进行测试。参考文档描述了不同的设置。 我正在使用@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)。我有一个案例。假设某个事务正在运行以从中获取数据,并且当时二级缓存有数据。同时,另一个线程在前一个事务尚未完成时驱逐所有区域缓存。那么在这种情况下会发生什么。我可以从该事务中的缓存中获取 null 并且会发生数据库命中吗?有没有可能出现问题? 您应该根据您的特定上下文编写测试。根据文档,读写似乎与您的情况相匹配,但请注意它有要求,所有详细信息都在此处(参见docs.jboss.org/hibernate/orm/4.3/devguide/en-US/html/…)【参考方案2】:

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

要清除二级缓存,请使用this code snippet

【讨论】:

对于现代版本的 Hibernate,最好遵循@dino 的回答。【参考方案3】:

如果您插入 Terracotta,您还可以运行 Terracotta 开发控制台,该控制台可以检查有关缓存的统计信息、打开和关闭缓存以及从用户界面清除缓存内容。

JMX bean 也提供此功能。

【讨论】:

【参考方案4】:

@Dino 的回答几乎对我有用,但我收到了来自sessionFactory.getCurrentSession() 的错误(未配置 currentSessionContext!)。我发现这对我有用:

    // 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.
    

【讨论】:

【参考方案5】:

如果要清除二级缓存,请使用apisessionFactory.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);
    

更多二级缓存详情refer

【讨论】:

【参考方案6】:

与@Dino 的回答相同,JPA 2.0 API 的缩短语法:

@Autowired
private EntityManagerFactory entityManagerFactory;

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

【讨论】:

【参考方案7】:

这个也可以

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

【讨论】:

HttpSession 和休眠会话是不同的东西。

以上是关于如何使用 Spring 清除所有 Hibernate 缓存(ehcache)?的主要内容,如果未能解决你的问题,请参考以下文章

grails 3(spring-boot) - 如何配置hibernate二级缓存

Spring中的HTTP请求后我们是不是需要清除MDC

Spring & JUnit 5 - 当@AfterAll 必须为静态时如何清除数据库

Spring Hiernate整合

弹簧或休眠连接泄漏

Spring Hiernate整合