我们有一个使用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的二级缓存知道没有真正的方法,一个实体在数据库中更改,除非它查询该实体(这是什么缓存保护你)。 所以,也许作为一个解决方案,我们可以简单地调用一些方法来迫使二级缓存驱逐一切(再次由于缺乏锁定的,你正在处理的事务从“阅读”或更新陈旧的数据风险并发控制)。
基于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);
}
}
SessionFactory的有很多evict()
正是为了这一目的的方法:
sessionFactory.evict(MyEntity.class); // remove all MyEntity instances
sessionFactory.evict(MyEntity.class, new Long(1)); // remove a particular MyEntity instances
Hibernate和JPA现在提供底层二级缓存直接访问:
sessionFactory.getCache().evict(..);
entityManager.getCache().evict(..)
我在寻找如何无效所有的Hibernate缓存,我发现这个有用的片段:
sessionFactory.getCache().evictQueryRegions();
sessionFactory.getCache().evictDefaultQueryRegion();
sessionFactory.getCache().evictCollectionRegions();
sessionFactory.getCache().evictEntityRegions();
希望它可以帮助别人。
你可以试试这样做:
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