Frage

Wir haben eine Anwendung, die das Ausschnitt zwischen Hibernate auf der 2. Ebene verwendet, um Datenbank -Hits zu vermeiden.

Ich habe mich gefragt, ob es eine einfache Möglichkeit gibt, den Hibernate -2. -Lei -Cache der Java -Anwendung zu ungültig zu machen, wenn ein externer Prozess wie ein MySQL -Administrator, der direkt mit der Datenbank verbunden ist (Aktualisieren/Einfügen/Löschen), direkt angeschlossen ist.

Wir benutzen Ehcache als unsere Cache -Implementierung der 2. Ebene.

Wir verwenden eine Mischung aus @cache (useage = cacheConcurrencyStrategy.read_write) und @cache (useage = cacheconcurcurrencyStrategy.nonstrict_read_write), und wir haben keine optimistische Parallelkontrolle mit der Verwendung von Zeitstempeln für jede Entität aktiviert.

Das SessionFactory enthält Methoden zum Verwalten des Cache der 2. Ebene: - Verwaltung der 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

Da wir jedoch einzelne Entitätsklassen mit @Cache kommentieren, gibt es keinen zentralen Ort für "zuverlässig" (z. B. keine manuellen Schritte), um dies der Liste hinzuzufügen.

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

Es gibt keinen wirklichen Weg für den 2. Level -Cache von Hibernate, um zu wissen, dass sich ein Unternehmen in der DB verändert hat, es sei denn, es fragt diese Entität ab (aus dem der Cache Ihnen schützt). Vielleicht könnten wir als Lösung einfach eine Methode aufrufen, um den Cache der zweiten Ebene zu erzwingen, um alles zu räumen (erneut aufgrund mangelnder Sperren und Gleichzeitregelung riskieren Sie Transaktionen im Bereich "Lesen" oder Aktualisierung von abgestandenen Daten).

War es hilfreich?

Lösung

Bezogen auf CHSSPLY76 Kommentare hier sind eine Methode, die alle Entitäten aus dem Cache der 2. Ebene räumt (wir können diese Methode Administratoren über JMX oder andere Admin -Tools aussetzen):

/**
 * 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);
    }
}

Andere Tipps

SessionFactory hat viel evict() Methoden genau für diesen Zweck:

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

Sowohl Hibernate als auch JPA bieten jetzt einen direkten Zugriff auf den zugrunde liegenden Cache der 2. Ebene:

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

Ich habe gesucht, wie man alle Hibernate -Caches ungültig macht, und fand diesen nützlichen Ausschnitt:

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

Hoffe es hilft jemand anderem.

Sie können versuchen, dies zu tun:

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

Ich hoffe, es hilft.

Eine Sache, die bei der Verwendung verteilter Cache berücksichtigt werden muss, ist, dass QueryCache lokal ist und es auf einem Knoten zu räumen, ihn nicht aus anderen zu erkennen. Ein weiteres Problem ist, dass die Evicing -Entitätsregion ohne Räumung der Abfragebereich n+1 ausgewählt wird, wenn Sie versuchen, das Datum vom Abfrage -Cache abzurufen. Gute Lesungen zu diesem Thema hier.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top