Hvorfor har du brug for en forespørgselscache

Lad os omskrive vores eksempel med at få medarbejdere i HQL:

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

assertTrue(director1 != director2);

Resultaterne af sådanne forespørgsler gemmes ikke af hverken første eller andet niveaus cache.

Det er præcis her, forespørgselscachen kan bruges . Den er også deaktiveret som standard. For at aktivere det skal du tilføje følgende linje til konfigurationsfilen:

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

Men dette er kun halvdelen af ​​løsningen. Vi har aktiveret forespørgselscachen, men vi skal også angive, hvilke forespørgselsresultater vi vil cache. Dette skal skrives i forespørgslen:

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

Forespørgselscachen ligner en cache på andet niveau. Men i modsætning til det, her er nøglen til cachedata ikke objektidentifikatoren, men sættet af forespørgselsparametre. Og selve dataene er identifikatorerne for de objekter, der matcher forespørgselskriterierne. Det er således rationelt at bruge denne cache med cache på andet niveau.

Rydder cachen

En af de vigtige opgaver, når du arbejder med en cache, er at sikre, at cachelagrede objekter ændres og fjerne dem fra cachen (eller opdatere dem). Hibernate gør dette meget godt. Nogle gange ser det endda ud til, at han er styret af reglen "ryd cachen i enhver uforståelig situation."

Lad os sige, at du vil opdatere brugerdata via HQL:

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

Hibernate kan ikke vide præcis, hvad der er ændret i databasen, men det ved, at du ændrer et Employee-objekt. Derfor vil Hibernate efter at have udført denne forespørgsel slette alle objekter af typen Employee fra sin cache.

Men NativeQuery fungerer endnu mere interessant:

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

En indbygget SQL-forespørgsel til databasen er blevet udført. Det betyder, at noget er ændret i databasen - anmodningen blev kaldt i executeUpdate()- metoden . Derfor vil Hibernate i dette tilfælde spille det sikkert og fjerne alle objekter af alle typer fra sin cache .

Hvordan kan du lide det? Du ringer til en harmløs anmodning, og Hibernate som svar sletter alle data fra cachen! Dette er bestemt bedre, end hvis han holdt genstande, der adskiller sig fra basen, men det er det!

Derfor fandt skaberne af Hibernate hurtigt ud af, hvordan de kunne hjælpe Hibernate i dette tilfælde. Du kan fortælle den, hvilken enhedstype den skal fjerne fra cachen:

Query nativeQuery = session.createNativeQuery("update employee set name=’Alex’ where id = 4");
nativeQuery.unwrap(org.hibernate.SQLQuery.class).addSynchronizedEntityClass(Employee.class);
nativeQuery.executeUpdate();
Bemærkning . Native select- forespørgsler tømmer ikke cachen , kun indsætte, opdatere, slette, procedurekalde osv.

Manuel cacherydning

Af visse grunde vil du måske selv slette et objekt fra cachen. Dette kan gøres på forskellige måder.

Bemærk . Objekter i cachen gemmes i grupper kaldet regioner . Som standard er regionsnavnet det samme som klassenavnet. Derfor, hvis du har objekter af typen com.codegym.Employee , så vil de alle blive gemt i en gruppe (region) med navnet " com.codegym.employee ".

Hvis du vil have adgang til cachen og gøre noget med den, kan du gøre det med SessionFactory-objektet og getCache ()- metoden :

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

Hvis du vil slette data fra alle grupper (regioner), skal du køre følgende forespørgsel:

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

For at fjerne et objekt fra cachen skal du videregive dets navn (type) og id. Du kan gøre dette på to måder:

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

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

Du kan også kontrollere, om et bestemt objekt er i cachen:

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