2009-10-21 13 views
22

Mamy aplikację, która używa pamięci podręcznej Hibernuj na drugim poziomie, aby uniknąć trafień bazy danych.Unieważnianie pamięci podręcznej drugiego poziomu Hibernacji, gdy inny proces modyfikuje bazę danych

Zastanawiam się, czy istnieje prosty sposób unieważnienia pamięci podręcznej Hibernuj 2nd poziomu aplikacji Java, gdy proces zewnętrzny, taki jak administrator MySQL, jest bezpośrednio podłączony do modyfikacji bazy danych (aktualizacja/wstawienie/usunięcie).

Używamy EHCache jako naszej implementacji pamięci podręcznej drugiego poziomu.

Używamy mieszankę @Cache (wykorzystanie = CacheConcurrencyStrategy.READ_WRITE) i @Cache (użytkowania = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) i nie mamy optymistyczne kontroli współbieżności włączona za pomocą znaczników czasu na każdej jednostce.

SessionFactory zawiera metody zarządzania cache poziom 2: - Managing the 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 

Ale dlatego, że opisywanie poszczególnych klas encji z @Cache, nie ma centralne miejsce dla nas „wiarygodnie” (np brak instrukcji kroki) dodaj to do listy.

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

Nie ma prawdziwego sposób pamięci podręcznej poziomu 2 Hibernate wiedzieć, że jednostka zmieniła w DB, chyba że jednostka zapytań (czyli to, co cache chroni Cię przed). Może więc jako rozwiązanie możemy po prostu wywołać pewną metodę wymuszającą pamięć podręczną drugiego poziomu w celu eksmisji wszystkiego (ponownie z powodu braku kontroli blokowania i współbieżności ryzykujesz transakcje w trakcie "czytania" lub aktualizowania nieaktualnych danych).

Odpowiedz

14

podstawie ChssPly76's komentarzy Oto metoda, która evicts wszystkie podmioty z cache 2 poziomu (możemy odsłonić tę metodę do adminów przez JMX lub innego administratora narzędzia):

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

Chcę wyczyścić dane pamięci podręcznej z pamięci podręcznej drugiego poziomu, wywołując poniższą metodę: - sessionFactory.getCache(). EvictEntityRegions(); Po prostu chcę wiedzieć, czy istnieje jakakolwiek szkoda w tym działaniu? Na przykład: - Co się stanie, jeśli spróbuję wyczyścić pamięć podręczną w trakcie transakcji? –

11

SessionFactory ma mnóstwo evict() metodami właśnie do tego celu:

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

Czy istnieje wiarygodny sposób eksmitowania wszystkich wystąpień wszystkich klas z komentarzem @Cache z pamięci podręcznej drugiego poziomu. Zwykle przypisujemy klasy, aby włączyć pamięć podręczną drugiego poziomu, tak więc nie ma jednego centralnego miejsca do aktualizacji kodu, gdy nowa jednostka zostanie dodana do pamięci podręcznej drugiego poziomu. – Dougnukem

+1

Szczerze mówiąc, eksmisja ** wszystkich ** wystąpień wydaje się raczej skrajnym przypadkiem. Zrób to dość często i może skończyć się wydajnością gorszą niż bez pamięci podręcznej. Mimo to można uzyskać nazwy wszystkich obiektów za pomocą metody 'getAllClassMetadata()' (nazwy są kluczami zwróconej mapy) i wywołać 'evictEntity()' dla każdego. – ChssPly76

+0

Jest to bardzo rzadka okazja, kiedy musimy wykonać produkcję "HOTFIX" bazy danych bez usuwania serwerów, a nasze istniejące narzędzia administratora usług klienta nie mogą tego zrobić (i raczej nie ujawnimy niektórych poleceń administratora, pozwala ci wykonać dowolny dowolny SQL). Następnie, zezwalając zewnętrznemu administratorowi na wykonanie SQL, tracimy wszystkie inspekcje transakcji i logowanie. – Dougnukem

8

Zarówno hibernacji i WZP teraz zapewniają bezpośredni dostęp do podstawowej pamięci podręcznej poziom 2:

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

szukałem sposobu, aby unieważnić wszystkie bufory Hibernate i znalazłem ten użyteczny fragment:

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

Nadzieja pomaga komuś innemu.

1

można spróbować w ten sposób:

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

Mam nadzieję, że to pomaga.

Powiązane problemy