一尘不染

当另一个进程修改数据库时,Hibernate 2级缓存无效

hibernate

我们有一个使用Hibernate二级缓存以避免数据库命中的应用程序。

我想知道当外部进程(例如MySQL管理员)直接连接到修改数据库(更新/插入/删除)时,是否有一些简单的方法可以使Java应用程序的Hibernate
2级缓存无效。

我们正在使用EHCache作为我们的第二级缓存实现。

我们将@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)和@Cache(usage =
CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)混合使用,并且没有对每个实体使用时间戳启用乐观并发控制。

SessionFactory包含管理二级缓存的方法:-
管理缓存

sessionFactory.evict(Cat.class, catId); //evict a particular Cat
sessionFactory.evict(Cat.class);  //evict all Cats
sessionFactory.evictCollection("Cat.kittens", catId); //evict a particular collection of kittens
sessionFactory.evictCollection("Cat.kittens"); //evict all kitten collections

但是,因为我们使用@Cache注释了各个实体类,所以我们没有“可靠地”(例如没有手动步骤)将其添加到列表的中心位置。

// Easy to forget to update this to properly evict the class
public static final Class[] cachedEntityClasses = {Cat.class, Dog.class, Monkey.class}

public void clear2ndLevelCache() {
  SessionFactory sessionFactory = ...   //Retrieve SessionFactory

   for (Class entityClass : cachedEntityClasses) {
       sessionFactory.evict(entityClass);
   }
}

Hibernate的二级缓存没有真正的方法知道数据库中的某个实体已更改,除非它查询该实体(这是缓存保护了您的实体)。因此,也许作为解决方案,我们可以简单地调用某种方法来强制第二级缓存将所有内容逐出(同样由于缺少锁定和并发控制,您有可能因“读取”或更新陈旧数据而导致进行中的交易)。


阅读 185

收藏
2020-06-20

共1个答案

一尘不染

根据ChssPly76的评论,这是一种从第二级缓存中逐出所有实体的方法(我们可以通过JMX或其他管理工具向管理员公开此方法):

/**
 * 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();
        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);
    }
}
2020-06-20