Hibernate当另一个进程修改数据库时,第二级缓存无效 [英] Hibernate 2nd level cache invalidation when another process modifies the database

查看:171
本文介绍了Hibernate当另一个进程修改数据库时,第二级缓存无效的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

We have an application that uses Hibernate's 2nd level caching to avoid database hits.

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

I was wondering if there is some easy way to invalidate the Java application's Hibernate 2nd level cache when an outside process such as a MySQL administrator directly connected to modify the database (update/insert/delete).

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

We are using EHCache as our 2nd level cache implementation.

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

We use a mix of @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) and @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE), and we don't have Optimistic concurrency control enabled using timestamps on each entity.

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

The SessionFactory contains methods to manage the 2nd level cache: - Managing the Caches

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注释单个实体类,对我们来说可靠(例如没有手动步骤)将它添加到列表中。

But because we annotate individual entity classes with @Cache, there's no central place for us to "reliably" (e.g. no manual steps) add that to the list.

// 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的二级缓存一个实体在DB中改变,除非它查询那个实体(这是缓存正在保护你)。因此,也许作为一个解决方案,我们可以简单地调用一些方法来强制第二级缓存驱逐一切(再次因为缺乏锁定和并发控制你冒着从读取或更新过时的数据的事务)。

There's no real way for Hibernate's 2nd level cache to know that an entity changed in the DB unless it queries that entity (which is what the cache is protecting you from). So maybe as a solution we could simply call some method to force the second level cache to evict everything (again because of lack of locking and concurrency control you risk in progress transactions from "reading" or updating stale data).

推荐答案

根据 ChssPly76的评论,这里有一个方法,从二级缓存中删除所有实体(我们可以通过JMX或其他管理工具将此方法公开给管理员):

Based on ChssPly76's comments here's a method that evicts all entities from 2nd level cache (we can expose this method to admins through JMX or other admin tools):

/**
 * 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);
    }
}

这篇关于Hibernate当另一个进程修改数据库时,第二级缓存无效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆