Willkommen beim Hibernate Caching – Beispiel für den First-Level-Cache. Vor kurzem haben wir uns die Hibernate-Architektur, das Hibernate-Mapping und die Verwendung von HQL zum Ausführen von SQL-Abfragen auf objektorientierte Weise angesehen. Heute werden wir uns einen der wichtigen Aspekte von Hibernate – den Hibernate-Cache – genauer ansehen.
Hibernate-Caching
Der Hibernate-Cache kann sehr nützlich sein, um eine schnelle Anwendungsleistung zu erreichen, wenn er richtig verwendet wird. Die Idee hinter dem Cache besteht darin, die Anzahl der Datenbankabfragen zu reduzieren und somit die Durchsatzzeit der Anwendung zu verringern. Hibernate bietet verschiedene Arten von Cache-Mechanismen:
- Erste Stufe Cache: Der Hibernate First Level Cache ist mit dem Session-Objekt verbunden. Der Hibernate First Level Cache ist standardmäßig aktiviert, und es gibt keine Möglichkeit, ihn zu deaktivieren. Hibernate stellt jedoch Methoden bereit, mit denen ausgewählte Objekte aus dem Cache gelöscht oder der Cache vollständig geleert werden können. Ein in einer Session zwischengespeichertes Objekt ist für andere Sessions nicht sichtbar, und wenn die Session geschlossen wird, gehen auch alle zwischengespeicherten Objekte verloren.
- Zweite Stufe Cache: Der Hibernate Second Level Cache ist standardmäßig deaktiviert, aber wir können ihn durch Konfiguration aktivieren. Derzeit bieten EHCache und Infinispan Implementierungen für den Hibernate Second Level Cache, die wir verwenden können. Dies werden wir im nächsten Tutorial zum Hibernate-Caching genauer betrachten.
- Abfrage-Cache: Hibernate kann auch das Ergebnis eines Abfrage-Resultsets zwischenspeichern. Der Hibernate Query Cache speichert nicht den Zustand der tatsächlichen Entitäten im Cache; er speichert nur Bezeichnerwerte und Ergebnisse von Werttypen. Daher sollte er immer in Verbindung mit dem Second-Level-Cache verwendet werden.
Hibernate-Caching – Beispiel für den First Level Cache
Für mein Beispielprogramm zum ersten Ebenen-Cache von Hibernate verwende ich dieselbe Konfiguration wie im HQL-Beispiel. Sie können das überprüfen und die Tabellen konfigurieren sowie mit Dummy-Daten bevölkern. Lassen Sie uns zuerst das Programm, seine Ausgabe betrachten und dann einige wichtige Punkte zum Hibernate First Level Cache durchgehen. HibernateCacheExample.java
package com.journaldev.hibernate.main;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import com.journaldev.hibernate.model.Employee;
import com.journaldev.hibernate.util.HibernateUtil;
public class HibernateCacheExample {
public static void main(String[] args) throws InterruptedException {
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
Session session = sessionFactory.getCurrentSession();
Transaction tx = session.beginTransaction();
//Holen Sie den Mitarbeiter mit der ID=1
Employee emp = (Employee) session.load(Employee.class, new Long(1));
printData(emp,1);
//Warten Sie eine Weile, um die Daten im Backend zu ändern
Thread.sleep(10000);
//Holen Sie dieselben Daten erneut ab, überprüfen Sie die Protokolle, dass keine Abfrage ausgeführt wurde
Employee emp1 = (Employee) session.load(Employee.class, new Long(1));
printData(emp1,2);
//Neue Sitzung erstellen
Session newSession = sessionFactory.openSession();
//Holen Sie den Mitarbeiter mit der ID=1, notice the logs for query
Employee emp2 = (Employee) newSession.load(Employee.class, new Long(1));
printData(emp2,3);
//START: Beispiel für Entfernen, um ein bestimmtes Objekt aus dem Hibernate First Level Cache zu entfernen
//Holen Sie den Mitarbeiter mit der ID=2, das erste Mal daher Abfrage in den Protokollen
Employee emp3 = (Employee) session.load(Employee.class, new Long(2));
printData(emp3,4);
//Entfernen Sie das Mitarbeiterobjekt mit der ID=1
session.evict(emp);
System.out.println("Session Contains Employee with id=1?"+session.contains(emp));
//Da das Objekt aus dem First Level Cache entfernt ist, sehen Sie eine Abfrage in den Protokollen
Employee emp4 = (Employee) session.load(Employee.class, new Long(1));
printData(emp4,5);
//Dieses Objekt ist immer noch vorhanden, daher sehen Sie keine Abfrage in den Protokollen
Employee emp5 = (Employee) session.load(Employee.class, new Long(2));
printData(emp5,6);
//END: Beispiel für Entfernen
//START: Beispiel für Löschen, um alles aus dem First Level Cache zu entfernen
session.clear();
Employee emp6 = (Employee) session.load(Employee.class, new Long(1));
printData(emp6,7);
Employee emp7 = (Employee) session.load(Employee.class, new Long(2));
printData(emp7,8);
System.out.println("Session Contains Employee with id=2?"+session.contains(emp7));
tx.commit();
sessionFactory.close();
}
private static void printData(Employee emp, int count) {
System.out.println(count+":: Name="+emp.getName()+", Zipcode="+emp.getAddress().getZipcode());
}
}
Wenn wir das obige Beispiel ausführen, enthält die Ausgabe viele Informationen zu Hibernate. Wir sind jedoch hauptsächlich an unserer codespezifischen Ausgabe und den von Hibernate zum Laden der Daten ausgeführten Abfragen interessiert. Der Auszug aus der Ausgabe sieht wie folgt aus.
Hibernate Configuration loaded
Hibernate serviceRegistry created
Hibernate: select employee0_.emp_id as emp_id1_1_0_, employee0_.emp_name as emp_name2_1_0_, employee0_.emp_salary as emp_sala3_1_0_, address1_.emp_id as emp_id1_0_1_, address1_.address_line1 as address_2_0_1_, address1_.city as city3_0_1_, address1_.zipcode as zipcode4_0_1_ from EMPLOYEE employee0_ left outer join ADDRESS address1_ on employee0_.emp_id=address1_.emp_id where employee0_.emp_id=?
1:: Name=Pankaj, Zipcode=95129
2:: Name=Pankaj, Zipcode=95129
Hibernate: select employee0_.emp_id as emp_id1_1_0_, employee0_.emp_name as emp_name2_1_0_, employee0_.emp_salary as emp_sala3_1_0_, address1_.emp_id as emp_id1_0_1_, address1_.address_line1 as address_2_0_1_, address1_.city as city3_0_1_, address1_.zipcode as zipcode4_0_1_ from EMPLOYEE employee0_ left outer join ADDRESS address1_ on employee0_.emp_id=address1_.emp_id where employee0_.emp_id=?
3:: Name=PankajK, Zipcode=95129
Hibernate: select employee0_.emp_id as emp_id1_1_0_, employee0_.emp_name as emp_name2_1_0_, employee0_.emp_salary as emp_sala3_1_0_, address1_.emp_id as emp_id1_0_1_, address1_.address_line1 as address_2_0_1_, address1_.city as city3_0_1_, address1_.zipcode as zipcode4_0_1_ from EMPLOYEE employee0_ left outer join ADDRESS address1_ on employee0_.emp_id=address1_.emp_id where employee0_.emp_id=?
4:: Name=David, Zipcode=95051
Session Contains Employee with id=1?false
Hibernate: select employee0_.emp_id as emp_id1_1_0_, employee0_.emp_name as emp_name2_1_0_, employee0_.emp_salary as emp_sala3_1_0_, address1_.emp_id as emp_id1_0_1_, address1_.address_line1 as address_2_0_1_, address1_.city as city3_0_1_, address1_.zipcode as zipcode4_0_1_ from EMPLOYEE employee0_ left outer join ADDRESS address1_ on employee0_.emp_id=address1_.emp_id where employee0_.emp_id=?
5:: Name=Pankaj, Zipcode=95129
6:: Name=David, Zipcode=95051
Hibernate: select employee0_.emp_id as emp_id1_1_0_, employee0_.emp_name as emp_name2_1_0_, employee0_.emp_salary as emp_sala3_1_0_, address1_.emp_id as emp_id1_0_1_, address1_.address_line1 as address_2_0_1_, address1_.city as city3_0_1_, address1_.zipcode as zipcode4_0_1_ from EMPLOYEE employee0_ left outer join ADDRESS address1_ on employee0_.emp_id=address1_.emp_id where employee0_.emp_id=?
7:: Name=Pankaj, Zipcode=95129
Hibernate: select employee0_.emp_id as emp_id1_1_0_, employee0_.emp_name as emp_name2_1_0_, employee0_.emp_salary as emp_sala3_1_0_, address1_.emp_id as emp_id1_0_1_, address1_.address_line1 as address_2_0_1_, address1_.city as city3_0_1_, address1_.zipcode as zipcode4_0_1_ from EMPLOYEE employee0_ left outer join ADDRESS address1_ on employee0_.emp_id=address1_.emp_id where employee0_.emp_id=?
8:: Name=David, Zipcode=95051
Session Contains Employee with id=2?true
Wichtige Punkte zum First-Level-Cache in Hibernate
Wichtige Punkte zum First-Level-Cache in Hibernate, die aus dem obigen Programm abgeleitet werden können, sind:
- Der Hibernate First-Level-Cache ist standardmäßig aktiviert, es sind keine Konfigurationen erforderlich.
- Der Hibernate First-Level-Cache ist sitzungsspezifisch. Wenn wir dieselben Daten in derselben Sitzung abrufen, wird keine Abfrage ausgeführt. In einer anderen Sitzung wird jedoch eine Abfrage zum Laden der Daten ausgeführt.
- Der Hibernate First-Level-Cache kann alte Werte enthalten. Wie oben zu sehen ist, habe ich mein Programm 10 Sekunden lang angehalten und in dieser Zeit den Wert (Name von Pankaj zu PankajK) in der Datenbank aktualisiert, aber in derselben Sitzung wurde dies nicht reflektiert. In einer anderen Sitzung haben wir den aktualisierten Wert erhalten.
- Wir können die Methode
evict()
der Sitzung verwenden, um ein einziges Objekt aus dem Hibernate First-Level-Cache zu entfernen. - Wir können die Methode
clear()
der Sitzung verwenden, um den Cache zu leeren, d.h. alle Objekte aus dem Cache zu löschen. - Wir können die Methode
contains()
der Sitzung verwenden, um zu überprüfen, ob ein Objekt im Hibernate-Cache vorhanden ist oder nicht. Wenn das Objekt im Cache gefunden wird, gibt es true zurück, sonst false. - Da Hibernate alle Objekte in den First-Level-Cache der Sitzung zwischenspeichert, ist es beim Ausführen von Massenabfragen oder Stapelaktualisierungen erforderlich, den Cache in bestimmten Intervallen zu leeren, um Speicherprobleme zu vermeiden.
Das war alles zum Hibernate Caching und zum Beispiel für den First-Level-Cache. In zukünftigen Beiträgen werden wir uns mit der Implementierung des Hibernate Second-Level-Cache – EHCache befassen.
Source:
https://www.digitalocean.com/community/tutorials/hibernate-caching-first-level-cache