Hibernate的二级缓存失效时,另一个进程修改数据库(Hibernate 2nd level c

2019-08-31 07:33发布

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

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

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

我们使用@Cache(使用率= CacheConcurrencyStrategy.READ_WRITE)和@Cache(用法= 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的二级缓存知道没有真正的方法,一个实体在数据库中更改,除非它查询该实体(这是什么缓存保护你)。 所以,也许作为一个解决方案,我们可以简单地调用一些方法来迫使二级缓存驱逐一切(再次由于缺乏锁定的,你正在处理的事务从“阅读”或更新陈旧的数据风险并发控制)。

Answer 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);
    }
}


Answer 2:

SessionFactory的有很多evict()正是为了这一目的的方法:

sessionFactory.evict(MyEntity.class); // remove all MyEntity instances
sessionFactory.evict(MyEntity.class, new Long(1)); // remove a particular MyEntity instances


Answer 3:

Hibernate和JPA现在提供底层二级缓存直接访问:

sessionFactory.getCache().evict(..);
entityManager.getCache().evict(..)


Answer 4:

我在寻找如何无效所有的Hibernate缓存,我发现这个有用的片段:

sessionFactory.getCache().evictQueryRegions();
sessionFactory.getCache().evictDefaultQueryRegion();
sessionFactory.getCache().evictCollectionRegions();
sessionFactory.getCache().evictEntityRegions();

希望它可以帮助别人。



Answer 5:

你可以试试这样做:

private EntityManager em;

public void clear2ndLevelHibernateCache() {
    Session s = (Session) em.getDelegate();
    SessionFactory sf = s.getSessionFactory();

    sf.getCache().evictQueryRegions();
    sf.getCache().evictDefaultQueryRegion();
    sf.getCache().evictCollectionRegions();
    sf.getCache().evictEntityRegions();

    return;
}

我希望它能帮助。



文章来源: Hibernate 2nd level cache invalidation when another process modifies the database