当前位置: 首页 > 面试题库 >

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

裴俊能
2023-03-14
问题内容

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


问题答案:

根据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);
    }
}


 类似资料:
  • 问题内容: 我有一个与MySQL数据库的Java程序连接,如何在同一连接上将当前数据库更改为另一个数据库? 我这样连接到MySQL: 经过一些操作后,我想在同一连接上连接到另一个mysql数据库。我怎样才能做到这一点? 我尝试使用: 但这不会更改要使用的数据库。 问题答案: 如MySQL文档中所述,您需要用于切换到另一个数据库。这也明确地说,你应该 不 执行切换。 发出此警告的原因是JDBC是数据

  • 我是hibernate的新手,我正在学习hibernate中的一级缓存。我担心一级缓存的一致性。 想象一下,我有两个独立的Web应用程序,它们可以读取/写入同一个数据库。两个应用程序都使用Hibernate。第一个应用程序由以下代码段组成。 第二个应用程序由以下代码组成。 假设第一个应用程序在上午10:00创建会话。第一个应用程序使该会话对象保持活动10分钟。同时,上午10点01分,第二个应用程序

  • 1、一级缓存:指的是mybatis中sqlSession对象的缓存,当我们执行查询以后,查询的结果会同时存入sqlSession中,再次查询的时候,先去sqlSession中查询,有的话直接拿出,当sqlSession消失时,mybatis的一级缓存也就消失了,当调用sqlSession的修改、添加、删除、commit()、close()等方法时,会清空一级缓存。 2、二级缓存:指的是mybati

  • 在MySQL 数据库中只能对数据库使用的字符集和校对规则进行修改,数据库的这些特性都储存在 db.opt 文件中。下面我们来介绍一下修改数据库的基本操作。 在 MySQL 中,可以使用 ALTER DATABASE 来修改已经被创建或者存在的数据库的相关参数。修改数据库的语法格式为: 语法说明如下: ALTER DATABASE 用于更改数据库的全局特性。 使用 ALTER DATABASE 需要

  • 数据库是具有不同属性的重要数据模型之一,您可以根据需要修改它们。 以下语句是命令的基本语法。 其中定义了要修改的属性,定义了要为该属性设置的值。 下表定义了用于更改数据库的受支持属性的列表。 编号 属性名称 描述 1 STATUS 定义不同属性之间的数据库状态。 2 IMPORTING 设置导入状态。 3 DEFAULTCLUSTERID 使用ID设置默认群集。 默认情况下是。 4 DATEFOR

  • 问题内容: 我需要将数据从一个数据库迁移到另一个数据库,两者都在同一本地系统上。 表和列的名称不同,我不能从旧数据库迁移所有列,因此 对我不起作用。 但我只有一个 我的查询中有什么错误,我该如何解决? 提前致谢 问题答案: 您的查询应如下所示: 更新 由于这个答案的关注程度超出了我的预期,因此我应该扩展这个答案。首先,从答案本身看可能并不明显,但各列不必具有相同的名称。因此,以下操作也将起作用(假