Waarom u een querycache nodig heeft

Laten we ons voorbeeld herschrijven door werknemers in HQL te krijgen:

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

assertTrue(director1 != director2);

De resultaten van dergelijke zoekopdrachten worden niet opgeslagen door de cache van het eerste of tweede niveau.

Dit is precies waar de querycache kan worden gebruikt . Het is ook standaard uitgeschakeld. Om het in te schakelen, voegt u de volgende regel toe aan het configuratiebestand:

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

Maar dit is slechts de helft van de oplossing. We hebben de querycache ingeschakeld, maar we moeten ook specificeren welke queryresultaten we willen cachen. Dit moet in de Query worden geschreven:

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

De querycache is vergelijkbaar met een cache op het tweede niveau. Maar in tegenstelling tot hier is de sleutel tot de cachegegevens niet de object-ID, maar de set queryparameters. En de gegevens zelf zijn de identifiers van de objecten die overeenkomen met de querycriteria. Het is dus rationeel om deze cache te gebruiken met de cache op het tweede niveau.

De cache wissen

Een van de belangrijke taken bij het werken met een cache is ervoor zorgen dat objecten in de cache veranderen en ze uit de cache verwijderen (of bijwerken). Hibernate doet dit heel goed. Soms lijkt het zelfs alsof hij zich laat leiden door de regel "wis de cache in elke onbegrijpelijke situatie".

Stel dat u gebruikersgegevens wilt bijwerken via HQL:

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

Hibernate kan niet precies weten wat er in de database is veranderd, maar het weet wel dat u een Employee-object aan het wijzigen bent. Daarom zal Hibernate na het uitvoeren van deze query alle objecten van het type Medewerker uit de cache verwijderen.

Maar NativeQuery werkt nog interessanter:

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

Er is een native SQL-query naar de database uitgevoerd. Dit betekent dat er iets is veranderd in de database - het verzoek is aangeroepen in de methode executeUpdate() . Daarom zal Hibernate in dit geval op veilig spelen en alle soorten objecten uit de cache verwijderen .

Wat vind je daarvan? U belt een onschadelijk verzoek en Hibernate wist als reactie alle gegevens uit de cache! Dit is zeker beter dan wanneer hij objecten bewaarde die afwijken van de basis, maar dat is alles!

Daarom kwamen de makers van Hibernate er snel achter hoe ze Hibernate in dit geval konden helpen. U kunt aangeven welk entiteitstype uit de cache moet worden verwijderd:

Query nativeQuery = session.createNativeQuery("update employee set name=’Alex’ where id = 4");
nativeQuery.unwrap(org.hibernate.SQLQuery.class).addSynchronizedEntityClass(Employee.class);
nativeQuery.executeUpdate();
Opmerking . Native select- query's spoelen de cache niet , alleen insert, update, delete, procedure calls, etc.

Handmatig cachegeheugen wissen

Om bepaalde redenen wilt u misschien zelf een object uit de cache verwijderen. Dit kan op verschillende manieren.

Opmerking . Objecten in de cache worden opgeslagen in groepen die regio's worden genoemd . Standaard is de regionaam hetzelfde als de klassenaam. Als u dus objecten van het type com.codegym.Employee hebt , worden ze allemaal opgeslagen in een groep (regio) met de naam " com.codegym.employee ".

Als u toegang wilt tot de cache en er iets mee wilt doen, kunt u dit doen met het SessionFactory-object en de methode getCache() :

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

Als u gegevens uit alle groepen (regio's) wilt verwijderen, moet u de volgende query uitvoeren:

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

Om één object uit de cache te verwijderen, moet u de naam (type) en id doorgeven. U kunt dit op twee manieren doen:

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

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

U kunt ook controleren of een bepaald object zich in de cache bevindt:

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