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

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

我们使用EHCache作为我们的二级缓存实现.

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

SessionFactory包含管理二级缓存的方法: -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注释单个实体类,所以我们没有"可靠地"(例如,没有手动步骤)将其添加到列表中的中心位置.

// 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的二级缓存没有真正的方法知道数据库中的某个实体发生了更改,除非它查询该实体(缓存正在保护您不受该实体的影响).因此,作为一种解决方案,我们可以简单地调用一些方法来强制二级缓存逐出所有内容(同样,由于缺乏锁定和并发控制,您有可能会在进行中的事务中"读取"或更新过时的数据).

推荐答案

基于ChssPly76's条 comments ,下面是一个从二级缓存中逐出所有实体的方法(我们可以通过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);
    }
}

Database相关问答推荐

Mongo DB使用一对多关系离开JOIN

网络分区恢复后副本的更新数据发生了什么

优雅地处理 EJB/JPA 环境中的约束冲突?

如何手动卸载 Oracle?

使用python为组中的每个元素添加一个序列号

我应该为 Realm 中的每个实体定义主键吗?

设计用于存储多人游戏的各种要求和统计数据的表格

向表中添加大量索引是否有缺点?

PHP + SQL Server - 如何设置连接字符集?

为什么 HikariCP 推荐固定大小的池以获得更好的性能

是什么导致pyodbcunable to connect to data source?

Oracle 的免费桌面客户端?

MongoDB 和 PostgreSQL 的思考

如果表不存在,如何使用 Derby Db 创建表

为 PHPMyadmin DB 自动生成数据库图?

一个表可以有两个外键吗?

如何在 SQL Server 中创建数据库的别名

Rails:'schema.rb' 中的版本号是否用于任何用途?

SQLite3 数据库的最大连接数是多少?

从 SQLite 导出到 SQL Server