Hvorfor du trenger en spørringsbuffer

La oss omskrive eksemplet vårt med å få ansatte 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);

Resultatene av slike spørringer lagres ikke av hverken første- eller andrenivåbufferen.

Det er akkurat her spørringsbufferen kan brukes . Den er også deaktivert som standard. For å aktivere det, legg til følgende linje i konfigurasjonsfilen:

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

Men dette er bare halve løsningen. Vi har aktivert spørringsbufferen, men vi må også spesifisere hvilke søkeresultater vi vil bufre. Dette må skrives i spørringen:

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

Spørringsbufferen ligner på en cache på andre nivå. Men, i motsetning til det, her er ikke nøkkelen til hurtigbufferdataene objektidentifikatoren, men settet med spørringsparametere. Og selve dataene er identifikatorene til objektene som samsvarer med søkekriteriene. Derfor er det rasjonelt å bruke denne cachen med cachen på andre nivå.

Tømmer bufferen

En av de viktige oppgavene når du arbeider med en hurtigbuffer er å sørge for at bufrede objekter endres og fjerne dem fra hurtigbufferen (eller oppdatere dem). Hibernate gjør dette veldig bra. Noen ganger ser det til og med ut til at han blir veiledet av regelen "tøm bufferen i enhver uforståelig situasjon."

La oss si at du vil oppdatere brukerdata via HQL:

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

Hibernate kan ikke vite nøyaktig hva som har endret seg i databasen, men den vet at du endrer et Employee-objekt. Derfor, etter å ha utført denne spørringen, vil Hibernate slette alle objekter av typen Employee fra cachen.

Men NativeQuery fungerer enda mer interessant:

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

En innebygd SQL-spørring til databasen er utført. Dette betyr at noe har endret seg i databasen - forespørselen ble kalt i executeUpdate()- metoden . Derfor, i dette tilfellet, vil Hibernate spille det trygt og fjerne alle objekter av alle typer fra cachen .

Hvordan liker du det? Du ringer en ufarlig forespørsel, og Hibernate som svar sletter all data fra cachen! Dette er absolutt bedre enn om han holdt gjenstander som skiller seg fra basen, men det er det!

Derfor fant skaperne av Hibernate raskt ut hvordan de kunne hjelpe Hibernate i dette tilfellet. Du kan fortelle den hvilken enhetstype som skal fjernes fra hurtigbufferen:

Query nativeQuery = session.createNativeQuery("update employee set name=’Alex’ where id = 4");
nativeQuery.unwrap(org.hibernate.SQLQuery.class).addSynchronizedEntityClass(Employee.class);
nativeQuery.executeUpdate();
Merknad . Innfødte utvalgsspørringer tømmer ikke hurtigbufferen , bare setter inn, oppdaterer, sletter , prosedyrekall osv.

Manuell tømming av cache

Av visse grunner kan det være lurt å slette et objekt fra hurtigbufferen selv. Dette kan gjøres på forskjellige måter.

Merk . Objekter i hurtigbufferen er lagret i grupper kalt regioner . Som standard er regionnavnet det samme som klassenavnet. Derfor, hvis du har objekter av typen com.codegym.Employee , vil alle av dem bli lagret i en gruppe (region) med navnet " com.codegym.employee ".

Hvis du vil ha tilgang til cachen og gjøre noe med den, kan du gjøre det med SessionFactory-objektet og getCache () -metoden :

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

Hvis du vil slette data fra alle grupper (regioner), må du kjøre følgende spørring:

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

For å fjerne ett objekt fra hurtigbufferen, må du sende inn navnet (type) og id. Du kan gjøre dette på to måter:

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

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

Du kan også sjekke om et bestemt objekt er i hurtigbufferen:

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