Warum Sie einen Abfragecache benötigen

Lassen Sie uns unser Beispiel mit der Einstellung von Mitarbeitern in HQL umschreiben:

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

assertTrue(director1 != director2);

Die Ergebnisse solcher Abfragen werden weder im Cache der ersten noch der zweiten Ebene gespeichert .

Genau hier kann der Query-Cache eingesetzt werden . Es ist auch standardmäßig deaktiviert. Um es zu aktivieren, fügen Sie der Konfigurationsdatei die folgende Zeile hinzu:

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

Aber das ist nur die halbe Lösung. Wir haben den Abfragecache aktiviert, müssen aber auch angeben, welche Abfrageergebnisse wir zwischenspeichern möchten. Dies muss in die Abfrage geschrieben werden:

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

Der Abfragecache ähnelt einem Cache der zweiten Ebene. Aber im Gegensatz dazu ist hier der Schlüssel zu den Cache-Daten nicht die Objektkennung, sondern der Satz von Abfrageparametern. Und die Daten selbst sind die Identifikatoren der Objekte, die den Abfragekriterien entsprechen. Daher ist es sinnvoll, diesen Cache mit dem Second-Level-Cache zu verwenden.

Cache leeren

Eine der wichtigen Aufgaben bei der Arbeit mit einem Cache besteht darin, sicherzustellen, dass sich zwischengespeicherte Objekte ändern, und sie aus dem Cache zu entfernen (oder zu aktualisieren). Hibernate macht das sehr gut. Manchmal scheint es sogar, dass er sich von der Regel leiten lässt: „Leere den Cache in jeder unverständlichen Situation.“

Angenommen, Sie möchten Benutzerdaten über HQL aktualisieren:

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

Hibernate kann nicht genau wissen, was sich in der Datenbank geändert hat, aber es weiß, dass Sie ein Mitarbeiterobjekt ändern. Daher löscht Hibernate nach der Ausführung dieser Abfrage alle Objekte vom Typ Employee aus seinem Cache.

Aber NativeQuery funktioniert noch interessanter:

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

Eine native SQL-Abfrage an die Datenbank wurde ausgeführt. Das bedeutet, dass sich etwas in der Datenbank geändert hat – die Anfrage wurde in der MethodeexecuteUpdate() aufgerufen . Daher geht Hibernate in diesem Fall auf Nummer sicher und entfernt alle Objekte aller Art aus seinem Cache .

Wie gefällt dir das? Sie rufen eine harmlose Anfrage auf und Hibernate löscht als Antwort alle Daten aus dem Cache! Das ist sicherlich besser, als wenn er Gegenstände behalten würde, die sich von der Basis unterscheiden, aber das war’s!

Daher haben die Entwickler von Hibernate schnell herausgefunden, wie sie Hibernate in diesem Fall helfen können. Sie können ihm mitteilen, welcher Entitätstyp aus dem Cache entfernt werden soll:

Query nativeQuery = session.createNativeQuery("update employee set name=’Alex’ where id = 4");
nativeQuery.unwrap(org.hibernate.SQLQuery.class).addSynchronizedEntityClass(Employee.class);
nativeQuery.executeUpdate();
Bemerkung . Native Select- Abfragen leeren den Cache nicht , sondern nur durch Einfügen, Aktualisieren, Löschen, Prozeduraufrufe usw.

Manuelles Löschen des Caches

Aus bestimmten Gründen möchten Sie möglicherweise selbst ein Objekt aus dem Cache löschen. Dies kann auf unterschiedliche Weise erfolgen.

Hinweis . Objekte im Cache werden in Gruppen gespeichert, die als Regionen bezeichnet werden . Standardmäßig ist der Regionsname mit dem Klassennamen identisch. Wenn Sie also Objekte vom Typ com.codegym.Employee haben , werden alle in einer Gruppe (Region) mit dem Namen „ com.codegym.employee “ gespeichert.

Wenn Sie auf den Cache zugreifen und etwas damit machen möchten, können Sie dies mit dem SessionFactory-Objekt und der Methode getCache() tun :

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

Wenn Sie Daten aus allen Gruppen (Regionen) löschen möchten, müssen Sie die folgende Abfrage ausführen:

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

Um ein Objekt aus dem Cache zu entfernen, müssen Sie seinen Namen (Typ) und seine ID übergeben. Sie können dies auf zwei Arten tun:

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

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

Sie können auch überprüfen, ob sich ein bestimmtes Objekt im Cache befindet:

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