Parallelitätsstrategien
Nachdem Sie das Caching der zweiten Ebene in Hibernate aktiviert haben, müssen Sie Hibernate erklären, welche Entitätsobjekte wir wie zwischenspeichern möchten.
Zu diesem Zweck verfügt Hibernate über eine spezielle Annotation für Entity-Klassen – @Cache . Beispiel:
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
Diese Annotation muss für jede Entity-Entität geschrieben werden, für die wir den Second-Level-Cache verwenden möchten. Beispiel:
@Entity
@Table(name = "employee")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Employee {
@Id
private Integer id;
private Set<Task> tasks;
}
Hibernate verfügt über vier mögliche Zugriffsstrategien für eine zwischengespeicherte Entität, wenn von verschiedenen Threads aus darauf zugegriffen wird:
- schreibgeschützt
- lesen Schreiben
- nicht striktes Lesen/Schreiben
- transaktional
Nur lesen . Eine datengerechte Parallelitätsstrategie, die sich nie ändert. Hibernate speichert diese Objekte einfach in seinem Speicher. Verwenden Sie es nur für Referenzdaten.
Datenbanken speichern viele Informationen, die sich nie ändern. Beispielsweise führt eine Tabelle eine Liste von Ereignissen, die nur hinzugefügt, aber nie geändert oder entfernt werden. Wenn Sie mit dieser Tabelle über den Ruhezustand arbeiten müssen, ist die schreibgeschützte Caching-Strategie genau das Richtige für Sie.
Lesen-Schreiben (Lesen-Schreiben). Verwenden Sie diese Strategie für Daten, die hauptsächlich lesbar sind. Hibernate verfolgt jedoch Versuche, diese Daten zu ändern, obwohl davon ausgegangen wird, dass diese sehr selten sind.
Sie müssen hauptsächlich die Objekte zwischenspeichern, die sich selten ändern und häufig gelesen/angefordert werden. Wenn Sie solche Objekte haben, müssen Sie für sie die Lese-/Schreibstrategie verwenden.
Nicht striktes Lesen und Schreiben . Diese Strategie garantiert keine Konsistenz zwischen Cache und Datenbank. Verwenden Sie diese Strategie, wenn sich die Daten fast nie ändern und eine geringe Wahrscheinlichkeit veralteter Daten kein kritisches Problem darstellt.
Im Gegensatz zur Lese-/Schreibstrategie geht diese Strategie davon aus, dass veränderbare Daten nicht zum Lesen gesperrt sind. Dies kann dazu führen, dass das Objekt an einer Stelle geändert wird, während an einer anderen Stelle jemand die alte Version davon liest.
Beispielsweise hat ein Benutzer seinen Kommentar geändert, andere Benutzer sehen jedoch noch einige Zeit seine alte Version. Wenn dies für Sie kein Problem darstellt, verwenden Sie die nicht strikte Lese-/Schreibstrategie.
Transaktional . Verwenden Sie diese Strategie für hauptsächlich schreibgeschützte Daten, bei denen es wichtig ist, veraltete Daten in gleichzeitigen Transaktionen im seltenen Fall einer Aktualisierung zu verhindern.
Daten in einem Cache speichern
Ein weiteres wichtiges Detail zum Second-Level-Cache, das Sie beachten sollten, ist, dass Hibernate die Objekte Ihrer Klassen selbst nicht speichert. Es speichert Informationen als Arrays aus Zeichenfolgen, Zahlen usw.
Und der Objektbezeichner fungiert als Zeiger auf diese Informationen. Vom Konzept her ist dies so etwas wie eine Map, bei der die ID des Objekts der Schlüssel und die Datenarrays der Wert sind. Man kann es sich so vorstellen:
1 -> { "Ivanov", 1, null , {1,2,5} }
2 -> { "Petrov", 2, null , {1,2,5} }
3 -> { "Sidorov", 3, null , {1,2,5} }
Das ist sehr sinnvoll, wenn man bedenkt, wie viel zusätzlichen Speicher jedes Objekt beansprucht.
Darüber hinaus sollten Sie bedenken, dass die Abhängigkeiten Ihrer Entity-Klasse ebenfalls nicht standardmäßig zwischengespeichert werden. Wenn wir beispielsweise die obige Klasse Employee betrachten , wird beim Abrufen die Aufgabensammlung aus der Datenbank und nicht aus dem Cache der zweiten Ebene abgerufen .
Wenn Sie auch Abhängigkeiten zwischenspeichern möchten, sollte die Klasse folgendermaßen aussehen:
@Entity
@Table(name = "employee")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Employee {
@Id
private Integer id;
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
private Set<Task> tasks;
}
Und das letzte Detail: Das Lesen aus dem Cache der zweiten Ebene erfolgt nur, wenn das gewünschte Objekt nicht im Cache der ersten Ebene gefunden wurde.
CacheMode
Der Ruhezustand ermöglicht eine sehr flexible Caching-Verwaltung. Sie können den Cache-Modus für jede einzelne Sitzung oder sogar für jede Datenbankanfrage festlegen.
Es gibt fünf solcher Modi:
- ERHALTEN
- IGNORIEREN
- NORMAL
- SETZEN
- AKTUALISIERUNG
Die folgende Tabelle beschreibt ihre Arbeit:
CacheMode | Beschreibung |
---|---|
ERHALTEN | Daten werden aus dem Cache gelesen, aber nicht hinzugefügt. |
IGNORIEREN | Die Sitzung interagiert nicht mit dem Cache. |
NORMAL | Daten werden aus dem Cache gelesen und diesem hinzugefügt. |
SETZEN | Daten werden nie aus dem Cache entnommen, sondern diesem hinzugefügt. |
AKTUALISIERUNG | Daten werden nie aus dem Cache entnommen, sondern diesem hinzugefügt. In diesem Modus wird zusätzlich die Einstellung hibernate.cache.use_minimal_puts verwendet. |
Ein Beispiel für die Einstellung des Cache-Modus für eine Sitzung:
session.setCacheMode(CacheMode.GET);
Employee director = session.createQuery("from Employee where id = 4").uniqueResult();
Und auch ein Beispiel für die Einstellung des Modus für die Sitzung und die Anfrage:
session.setCacheMode(CacheMode.GET);
Query query = session.createQuery("from Employee where id = 4");
query.setCacheMode(CacheMode.IGNORE); // Ignore cache work for this request
Employee director = query.uniqueResult();