Unsere Datenschutzrichtlinie wird in Kürze aktualisiert. Bitte sehen Sie sich die Vorschau an.

Java EE 7 Grundkurs

Sperren von Datensätzen

Testen Sie unsere 2016 Kurse

10 Tage kostenlos!

Jetzt testen Alle Abonnements anzeigen
JPA-Applikationen verfügen über die Funktionalitäten, um einzelne Datensätze auf Ebene der Datenbank zu sperren sowie mit einer zusätzlichen Versionsinformation zu versehen.

Transkript

Auf Ebene der Java EE arbeiten Sie in einem Umfeld, in dem es parallele Zugriffe geben kann. Die müssen nicht nur von Ihrem Rechner ausgehen, sondern die können ja auch von anderen Rechnern ausgehen. Umso wichtiger ist es, sich klarzumachen, wie ich Datensätze in der JPA sperren kann, sodass letztlich meine Änderungen tatsächlich die Änderungen sind, die auch in der Datenbank landen, oder aber niemand anderes auf diesen Datensatz während eines bestimmten Zustandes zugreifen kann. Das werden wir in diesem Video vertiefen. JPA unterstützt zwei Arten des Sperrens von Datensätzen, nämlich das optimistische oder das pessimistische Sperren. Beide Arten werden auch gerne als "Locking" bezeichnet, also "Optimistic Locking" und "Pessimistic Locking". Optimistische Sperrung ist der Standard. Und die Begrifflichkeit "optimistisch" bezieht sich darauf, dass es eigentlich nicht wirklich eine Sperrung ist. Pessimistische Sperren gibt es auf Datenbankebene bereits seit 20, 25 Jahren, in der JPA allerdings erst seit einigen Jahren, nämlich seit der JPA-Version 2.0. Der Grund dafür ist, dass pessimistische Sperrungen deutlich mehr Performance auf der Datenbankebene kosten, weil sie auf der Datenbankebene auch umgesetzt werden. Sie sind dafür aber deutlich sicherer, denn man erhält einen exklusiven Lese- und Schreibschutz für den Datensatz. Optimistische Sperrungen werden mit Hilfe der Version-Annotation umgesetzt. Diese Annotation wird auf Ebene von Feldern definiert. Das entsprechende Feld wird von der JPA automatisch mit entsprechenden Inhalten befüllt. Und es muss dafür bestimmte Datentypen unterstützen, nämlich entweder numerische Datentypen wie int, short, long, oder java.sql.Timestamp. Das Feld ist unter Verwaltung der JPA. Und die JPA wird dann diese Versionsinformation, die darin steht, bei jedem Ändern des Datensatzes mit den Versionsinformationen in der Datenbank abgleichen. Gibt es dort Unterschiede? Dann wird die Änderung nicht durchgeführt und die Transaktion zurückgerollt. Da optimistische Sperrungen eigentlich keine Sperrungen sind, sondern lediglich von der Applikation ausgeführt werden, wenn der Datensatz aktualisiert werden soll, kann man den Datensatz jederzeit lesen und eigentlich auch jederzeit ändern. Die Überprüfung der Version erfolgt, wie bereits erwähnt, beim Commit der Transaktion durch die Applikation oder den JPA-Provider. Und wenn es nicht passt, dann gibt es eine Exception. Der ganz große Nachteil von optimistischen Sperrungen ist, dass das Ganze eben wirklich applikationsseitig umgesetzt ist. Das bedeutet: Wenn eine andere Applikation arbeitet, die diese Sperrungen nicht unterstützt oder ignoriert, dann passiert dort gar nichts. Nur Ihre Applikation wird entsprechend reagieren. Anders ist dies bei pessimistischen Sperrungen, denn hier ist der Datensatz exklusiv gesperrt, und die Sperrung ist auf Ebene der Datenbank umgesetzt. Wenn man sich nun vorstellt, dass man es mit einer Datenbank zu tun hat, auf die hunderte oder tausende Benutzer parallel zugreifen, kann man sich vorstellen, dass das eventuell ressourcenintensiv sein könnte. Damit ist aber sichergestellt, dass der Datensatz nicht in verschiedenen Transaktionen parallel manipuliert werden kann. Das können wir im Code ausdrücken. Und zwar, beim Aufruf der find-Methode können wir als Parameter einen LockModeType angeben, genauso wie es eine Extra-Methode "lock" gibt, wo ich einen spezifischen Datensatz locken kann. Und ich kann es ebenfalls auf Ebene von named queries zum Beispiel angeben. Schauen wir uns einmal an, wie wir eine optimistische Sperrung im Code umsetzen können. Wir sehen hier die Entität "Book". Diese Entität "Book" verfügt über ein privates Feld vom Typ "integer", was mit "Version" annotiert wird. Der Name dieses Feldes ist nicht wichtig. Das muss halt nur dem Spaltennamen in der Datenbank-Tabelle entsprechen. Dieses Feld verfügt, anders als die anderen Felder dieser Entität, nicht über Getter und Setter, wird also wirklich nur intern benutzt. In der Datenbank gibt es eine entsprechende Repräsentation dieses Feldes. Wir sehen hier die Struktur der Books-Tabelle. Und hier gibt es genau dasselbe Feld, nämlich "Version", vom Datentyp "integer". Mehr ist hierzu eigentlich nicht zu sagen. Wie gesagt: Verwaltet wird dieses Feld von der JPA. Diese Verwaltung findet unter der Haube statt. Sie wird immer dann angewendet, wenn ein Datensatz geupdatet wird. Das ist zum Beispiel der Fall bei einem "merge"-Statement. Dieses "merge"-Statement werden wir im Folgenden auch ein wenig missbrauchen. Sie müssen wissen: Wenn die JPA einen Datensatz updatet, dann gibt es einen Transaktionskontext. Dieser Transaktionskontext ist normalerweise vom Beginn einer Methode bis zum Ende einer Methode. Das bedeutet: Wenn ich so ein Statement ausführe, dann wird zwar der Datensatz geladen, weil man in der Datenbank ja die aktuellen Werte dieses Datensatzes beim "merge"-Statement sucht und dann später überschreibt. Dabei wird auch die aktuelle Version des Datensatzes geladen. Sie wird allerdings nicht abgefragt für die Aktualisierung, bis nicht diese komplette Methode verlassen ist, und die komplette Transaktion dann letztlich commited worden ist. Das werden wir uns jetzt zunutze machen, um einfach zu demonstrieren, wie sich das auswirkt, wenn während einer laufenden Transaktion die Versionsinformation geändert wird. Das werden wir direkt in der Datenbank dann machen. Um das Ganze auszuführen, werden wir die Applikation einmal starten und dann einen Datensatz ändern lassen. Wenn wir nun auf den Link "Ändern" klicken, wird die gerade eben gezeigte Update-Methode des Book-Managers aufgerufen. Dann haben wir zehn Sekunden Zeit, um, während der aktuelle Thread angehalten wird, die Datenbank zu manipulieren. Lassen Sie uns dies nun ausführen. Ich starte den Prozess, wechsle in die Datenbank, update die Versionsinformationen und dann wechseln wir zurück in die Webseite. Sie sehen: Die Webseite arbeitet noch. Und gleich werden wir einen Fehler sehen. Die Transaktion wurde nämlich zurückgerollt. Und wenn man sich die Fehlermeldung auf der Serverebene genauer anschaut, wird man erkennen können, dass die Versionsinformation halt nicht übereinstimmt, denn wir haben sie in der Zwischenzeit ja aktualisiert. Schauen wir uns noch einmal das Verhalten an, das wir haben, wenn wir die Versionsinformation nicht aktualisieren. Das heißt, ich entferne dieses Statement, das ich da gerade eben hatte, deploye die Applikation noch einmal neu und führe die Operation noch einmal aus. Dann werden Sie feststellen, dass das einwandfrei funktioniert. Ja, denn in der Zwischenzeit war es eben nicht möglich, dass eine neue Versionsinformation geschrieben worden ist. Sie sehen: Die Versionsinformation kann sehr hilfreich sein. Das optimistische Locking ist auch sehr einfach umzusetzen. Sie benötigen lediglich ein privates Feld, das mit Version annotiert ist.

Java EE 7 Grundkurs

Lernen Sie die Grundlagen der Programmierung mit Java EE 7 verstehen und anwenden.

6 Std. 4 min (44 Videos)
Derzeit sind keine Feedbacks vorhanden...
 

Dieser Online-Kurs ist als Download und als Streaming-Video verfügbar. Die gute Nachricht: Sie müssen sich nicht entscheiden - sobald Sie das Training erwerben, erhalten Sie Zugang zu beiden Optionen!

Der Download ermöglicht Ihnen die Offline-Nutzung des Trainings und bietet die Vorteile einer benutzerfreundlichen Abspielumgebung. Wenn Sie an verschiedenen Computern arbeiten, oder nicht den ganzen Kurs auf einmal herunterladen möchten, loggen Sie sich auf dieser Seite ein, um alle Videos des Trainings als Streaming-Video anzusehen.

Wir hoffen, dass Sie viel Freude und Erfolg mit diesem Video-Training haben werden. Falls Sie irgendwelche Fragen haben, zögern Sie nicht uns zu kontaktieren!