De ce aveți nevoie de un cache de interogări

Să rescriem exemplul nostru cu obținerea de angajați în HQL:

Employee director1 = session.createQuery("from Employee where id = 4").uniqueResult();
Employee director2 = session.createQuery("from Employee where id = 4").uniqueResult();

assertTrue(director1 != director2);

Rezultatele unor astfel de interogări nu sunt stocate nici de primul, nici de cel de-al doilea nivel cache.

Acesta este exact locul în care poate fi folosit cache-ul de interogări . De asemenea, este dezactivat implicit. Pentru a-l activa, adăugați următoarea linie la fișierul de configurare:

<property name="hibernate.cache.use_query_cache" value="true"/>

Dar aceasta este doar jumătate din soluție. Am activat memoria cache a interogărilor, dar trebuie să specificăm și rezultatele interogării pe care vrem să le memorăm. Acest lucru trebuie scris în Interogare:

Query query = session.createQuery("from Employee where id = 4");
query.setCacheable(true);
Employee director1 = query.uniqueResult();

Cache-ul de interogări este similar cu un cache de al doilea nivel. Dar, spre deosebire de acesta, aici cheia datelor cache nu este identificatorul obiectului, ci setul de parametri de interogare. Și datele în sine sunt identificatorii obiectelor care corespund criteriilor de interogare. Astfel, este rațional să folosiți acest cache cu al doilea nivel cache.

Golirea memoriei cache

Una dintre sarcinile importante atunci când lucrați cu un cache este să vă asigurați că obiectele din cache se schimbă și să le eliminați din cache (sau să le actualizați). Hibernate face acest lucru foarte bine. Uneori chiar pare că el este ghidat de regula „șterge cache-ul în orice situație de neînțeles”.

Să presupunem că doriți să actualizați datele utilizatorului prin HQL:

Query query = session.createQuery("update Employee set name=’Alex’ where id = 4")
query. executeUpdate();

Hibernate nu poate ști exact ce s-a schimbat în baza de date, dar știe că modificați un obiect Employee. Prin urmare, după executarea acestei interogări, Hibernate va șterge toate obiectele de tip Employee din cache-ul său.

Dar NativeQuery funcționează și mai interesant:

Query nativeQuery = session.createNativeQuery("update employee set name=’Alex’ where id = 4")
nativeQuery.executeUpdate();

A fost executată o interogare SQL nativă în baza de date. Aceasta înseamnă că ceva s-a schimbat în baza de date - cererea a fost apelată în metoda executeUpdate() . Prin urmare, în acest caz, Hibernate va juca în siguranță și va elimina toate obiectele de toate tipurile din memoria cache .

Cum iti place asta? Apelați o solicitare inofensivă, iar Hibernare, ca răspuns, șterge toate datele din cache! Acest lucru este cu siguranță mai bine decât dacă ar păstra obiecte care diferă de bază, dar asta este!

Prin urmare, creatorii Hibernate și-au dat seama rapid cum să-l ajute pe Hibernate în acest caz. Îi puteți spune ce tip de entitate să eliminați din cache:

Query nativeQuery = session.createNativeQuery("update employee set name=’Alex’ where id = 4");
nativeQuery.unwrap(org.hibernate.SQLQuery.class).addSynchronizedEntityClass(Employee.class);
nativeQuery.executeUpdate();
Observație . Interogările de selecție native nu șterg memoria cache , ci doar inserează, actualizează, șterg, apelează la procedură etc.

Ștergerea manuală a memoriei cache

Din anumite motive, poate doriți să ștergeți singur un obiect din cache. Acest lucru se poate face în moduri diferite.

Notă . Obiectele din cache sunt stocate în grupuri numite regiuni . În mod implicit, numele regiunii este același cu numele clasei. Prin urmare, dacă aveți obiecte de tip com.codegym.Employee , atunci toate acestea vor fi stocate într-un grup (regiune) cu numele „ com.codegym.employee ”.

Dacă doriți să accesați memoria cache și să faceți ceva cu el, o puteți face cu obiectul SessionFactory și metoda getCache() :

session.getSessionFactory().getCache().evictQueryRegion("com.codegym.employee”);

Dacă doriți să ștergeți datele din toate grupurile (regiunile), atunci trebuie să rulați următoarea interogare:

session.getSessionFactory().getCache().evictAllRegions();

Pentru a elimina un obiect din cache, trebuie să îi transmiteți numele (tipul) și id-ul. Puteți face acest lucru în două moduri:

session.getSessionFactory().getCache().evictEntityData("Employee, 4);

session.getSessionFactory().getCache().evictEntityData(com.codegym.Employee.class, 4);

De asemenea, puteți verifica dacă un anumit obiect este în cache:

session.getSessionFactory().getCache().containsEntity("Employee, 4);
session.getSessionFactory().getCache().containsEntity(com.codegym.Employee.class, 4);