手动更新数据库后清除Hibernate二级缓存

时间:2016-10-28 09:28:44

标签: java oracle hibernate caching ehcache

很快,我有一个实体映射到DB(Oracle)中的视图,启用了二级缓存(只读策略) - ehcache。

如果我手动更新数据库中的某些列,则不会更新缓存。

我没有找到任何方法来做到这一点。仅当通过Hibernate实体进行更新时才会这样做。

我可以以某种方式实现此功能吗?

也许Job可以监控表(或视图)?或者也许有一些方法可以通知Hibernate关于具体表中DB的变化。

感谢您将来的答案!

6 个答案:

答案 0 :(得分:2)

根据Hibernate JavaDoc,您可以使用org.hibernate.Cache.evictAllRegions()

  

evictAllRegions()从缓存中删除所有数据。

使用Session和SessionFactory:

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

1)如果你只需要更新一个实体(如果直接来自db,你只会更新某些实体)而不是整个会话,你可以使用

  

evictEntityRegion(Class entityClass)驱逐给定区域的所有实体数据(即

2)如果你有很多实体,可以直接从db更新,你可以使用这个方法从第二级缓存中驱逐所有实体(我们可以通过JMX或其他管理工具将此方法公开给管理员): / p>

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

3)这里有另一个apporche描述here for postgresql+hibernate,我认为你可以为Oracle做like this

答案 1 :(得分:2)

使用debezium从数据库中更新异步缓存。您可以访问https://debezium.io/

了解更多信息

本文也非常有帮助,因为它可以直接实现 https://debezium.io/blog/2018/12/05/automating-cache-invalidation-with-change-data-capture/

答案 2 :(得分:1)

如前所述,当您从后端手动更新数据库(不是通过应用程序/休眠会话)时,不会更新缓存。而且您的应用程序对此一无所知。

要告知应用有关更改的信息,您需要根据情况刷新与实体相关的整个缓存或部分缓存。这可以是两种方式之一:

1-重新启动应用程序-在这种情况下,将使用更新的数据库更改来重建缓存。

2-无需重新启动应用程序即可触发更新-无需重新启动应用程序,但您想告诉应用程序当前缓存无效,应该对其进行刷新。

  • 您可以通过多种方式将此外部推送提供给您的应用。很少 列在下面。

    1. 通过JMX。
    2. 通过带有已发布URL的servlet刷新缓存。在数据库中更改表后,单击URL。
    3. 在数据库上实现触发应用程序侦听器的触发器。
  • 在执行外部push / admin任务时,您可以根据需要调用合适的与缓存相关的方法来使缓存/刷新缓存无效。示例:Session.refresh(), Cache.evictAllRegions(), Cache.evictEntityRegion(entityName) etc,如其他帖子中所述。

答案 3 :(得分:0)

您可以使用session.refresh()方法重新加载当前在会话中保存的对象。

阅读object loading for more detail

答案 4 :(得分:0)

答案 5 :(得分:0)

从JEE 7.0开始:

myStatelessDaoBean.getSession().evict(MyEntity.class);