문제

데이터베이스 히트를 피하기 위해 Hibernate의 2 단계 캐싱을 사용하는 응용 프로그램이 있습니다.

MySQL 관리자와 같은 외부 프로세스가 데이터베이스 수정 (업데이트/삽입/삭제)을 직접 연결할 때 Java Application의 최대 절전 모드 2 레벨 캐시를 무효화하는 쉬운 방법이 있는지 궁금했습니다 (업데이트/삽입/삭제).

우리는 사용 중입니다 ehcache 우리의 두 번째 레벨 캐시 구현으로.

우리는 @cache (usage = cacheconcurrencystrategy.read_write)와 @cache (usage = cacheconcurrencystrategy.nactomprict_read_write)의 혼합을 사용하며 각 엔터티에서 타임 스탬프를 사용하여 낙관적 동의 컨트롤을 활성화하지 않습니다.

SessionFactory에는 2 단계 캐시를 관리하는 방법이 포함되어 있습니다. 캐시 관리

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의 2 단계 캐시가 엔티티 (캐시가 당신을 보호하는 것)를 쿼리하지 않는 한 DB에서 엔티티가 변경되었음을 알 수있는 실제 방법은 없습니다. 따라서 솔루션으로서 우리는 단순히 두 번째 레벨 캐시가 모든 것을 퇴거 시키도록 강요하는 방법을 호출 할 수 있습니다 (다시 잠금 및 동시성 제어로 인해 "읽기"또는 오래된 데이터를 업데이트 할 위험이 있습니다).

도움이 되었습니까?

해결책

기반 chssply76 주석 다음은 2 레벨 캐시에서 모든 엔티티를 발표하는 방법입니다 (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

최대 절전 모드와 JPA는 이제 기본 2 레벨 캐시에 직접 액세스 할 수 있습니다.

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

나는 모든 최대 절전 모드 캐시를 무효화하는 방법을 찾고 있었고이 유용한 스 니펫을 발견했습니다.

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

도움이되기를 바랍니다.

분산 된 캐시를 사용할 때 고려해야 할 한 가지는 QueryCache가 로컬이며 한 노드에서이를 퇴치한다고해서 다른 노드로부터 퇴거하지 않는다는 것입니다. 또 다른 문제는 쿼리 캐시에서 날짜를 검색하려고 할 때 쿼리 영역을 퇴치하지 않고 엔티티 영역을 퇴치하면 N+1 선택이 발생합니다. 이 주제에 대한 좋은 독서 여기.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top