Start / Seminare / Quarkus für Spring-Boot-Teams
Modul
Persistence mit Hibernate ORM und Panache
4 Kapitel in diesem Modul-Video · Laufzeit
Transkript
Der gesprochene Text dieses Moduls zum Mitlesen, Überfliegen und Durchsuchen. Ein Klick auf einen Zeitstempel springt an die Stelle im Video.
Persistence mit Hibernate ORM und Panache
0:00 Willkommen zum zweiten Tag. Wir beginnen mit der Persistenzschicht, und das aus gutem Grund: Sie entscheidet häufiger über Machbarkeit und Aufwand einer Migration als alles andere. Die Repositories sehen nach dem Umzug fast genauso aus wie vorher — die Kompatibilitätsschicht macht das möglich. Die eigentliche Frage ist eine andere: Welche Ihrer gewohnten Abfragen trägt diese Schicht mit, und welche nicht? Die Liste der Lücken ist kurz, aber sie hat es in sich.
0:27 Und danach sehen wir uns an, wie Quarkus selbst Datenzugriff denkt.
Persistence mit Hibernate ORM und Panache
0:32 Der zweite Tag ist der praktischste. Wir übertragen die Persistenz, klären Transaktionen und Querschnittliches, stellen die Tests um, ersetzen die Testinfrastruktur durch Dev Services und kümmern uns zum Schluss um Security und Messaging. Am Ende dieses Tages läuft Pfandkreis auf Quarkus — mit allem, was in der Praxis dazugehört.
Spring Data JPA und seine Quarkus-Kompatibilität
0:51 Beginnen wir wieder mit dem bequemen Weg. Die Repositories bleiben, wie sie sind — sehen wir uns an, wie weit das trägt. Die Extension erzeugt zur Bauzeit Implementierungen für die bekannten Repository-Schnittstellen — von der einfachen Variante bis zur vollständigen. Die erzeugten Repositories sind ganz normale Beans, und ändernde Methoden bekommen automatisch eine Transaktion.
1:15 Das Bild: Sie bringen Ihre Möbel mit, und jemand hat im neuen Haus dieselben Stellplätze vorbereitet. Auf den ersten Blick sieht alles aus wie vorher. Der Unterschied zeigt sich erst, wenn Sie eine Schublade aufziehen, die es hier gar nicht gibt. Erst die gute Nachricht, und sie ist umfangreicher, als viele erwarten. Abgeleitete Abfragemethoden funktionieren mitsamt den üblichen Zusätzen — Bereiche, Vergleiche, Sortierung, Begrenzung auf die ersten Treffer.
1:42 Eigene Abfragen über die Query-Annotation funktionieren ebenfalls, auch ändernde, auch mit benannten Parametern. Fragmente zur Erweiterung sind möglich, und sogar die Namensstrategien aus Spring Boot lassen sich einstellen. Für einen typischen CRUD-Dienst heißt das: Der überwiegende Teil Ihrer Repositories zieht unverändert um. Genau deshalb lohnt sich diese Zwischenstufe.
2:05 Und hier die Lücken. Lesen Sie diese Tabelle nicht als Mängelliste, sondern als Suchauftrag: Suchen Sie in Ihrem Code gezielt nach diesen fünf Dingen, bevor Sie irgendetwas planen. Besonders unangenehm sind zwei Einträge. Specifications und ähnliche Kriterien-Mechanismen stecken oft in einer generischen Suchfunktion, die vor Jahren jemand gebaut hat — und die niemand mehr ganz versteht.
2:26 Und die Sperr-Annotation verschwindet lautlos; niemand bekommt eine Fehlermeldung, nur die Kollisionssicherheit ist weg. Diese Suche ist eine halbe Stunde Arbeit und verändert unter Umständen Ihre gesamte Aufwandsschätzung. Der erste und zweite Punkt sind die eben genannten Lücken in ihrer typischen Erscheinungsform. Der dritte wiegt am schwersten: Die Sperr-Annotation fällt weg, und mit ihr eine Zusicherung, die nirgends dokumentiert ist, weil sie ja im Code stand.
2:53 Der vierte ist ein Haltungsfehler: Die Kompatibilitätsschicht wird zum Ziel erklärt. Die Quarkus-Dokumentation sagt sehr deutlich, dass sie als Übergang gedacht ist und empfiehlt Panache für die dauerhafte Lösung. Wer sie dauerhaft behält, trägt die Einschränkungen dauerhaft mit.
Hibernate ORM und Panache
3:10 Sehen wir uns also an, wie Quarkus selbst Datenzugriff denkt. Es gibt zwei Stile — und darunter arbeitet in beiden Fällen das Hibernate, das Sie kennen. Panache ist kein neues ORM, sondern eine Abkürzung über Hibernate. Es gibt zwei Stile: Active Record, bei dem die Entität selbst die Abfragemethoden trägt, und den Repository-Stil, den Sie aus Spring Data kennen. Beide bieten dieselben Methoden.
3:35 Das Bild: Dieselbe Küche, einmal mit allen Geräten in der Arbeitsplatte integriert, einmal mit einem separaten Geräteschrank. Welche Variante besser passt, hängt davon ab, wo in Ihrer Architektur die Fachlogik sitzt — nicht davon, welche moderner wirkt. Für Spring-Teams ist das hier der naheliegende Einstieg: ein Repository als Bean, und darin eine Methode mit einer Abfrage.
3:58 Interessant ist die Abfrage selbst — das ist kein eigener Dialekt, sondern ein Fragment der Abfragesprache von Hibernate. Sie schreiben nur den Teil hin, der Sie interessiert, den Rest ergänzt Panache. Sortierung und Parameter kommen als normale Argumente dazu. Und die Fußnote nennt den praktisch wichtigsten Teil: Blättern über Seiten oder Bereiche ist eingebaut, Sie brauchen dafür kein zusätzliches Konzept.
4:23 Diese Tabelle ist Ihr Umrechnungsblatt für die Übung. Das Muster dahinter ist einfach: Wo Spring Data den Methodennamen zur Abfrage macht, schreibt Panache die Abfrage direkt hin. Beides hat seinen Preis. Der Methodenname ist selbsterklärend, wird bei komplexen Bedingungen aber unlesbar lang. Das Abfragefragment ist kürzer und flexibler, dafür sehen Sie die Bedingung erst beim Lesen des Methodenkörpers.
4:47 Und die Fußnote verrät, was da wirklich passiert: Aus dem verkürzten Aufruf wird eine ganz gewöhnliche Abfrage — kein Zauber, nur weggelassener Text. Der erste Punkt betrifft eine Stilfrage mit Folgen: Active Record ist elegant, passt aber schlecht, wenn Ihre Fachlogik ohnehin in Diensten liegt. Der zweite irritiert Neulinge regelmäßig — öffentliche Felder in Entitäten.
5:09 Panache schreibt die Zugriffe hinter den Kulissen auf Getter und Setter um; es ist also nicht das, wonach es aussieht. Der dritte ist die eben erwähnte Verwechslung von Abkürzung und eigener Sprache. Und der vierte ist ein Teamproblem: Beide Stile mischen sich im selben Projekt, weil niemand sich einmal entschieden hat.
Transaktionen, Fetching und Schemapflege
5:28 Bleiben die drei Themen, die jede Persistenzschicht begleiten: Wann wird geschrieben, wann wird nachgeladen, und wer pflegt das Schema. Drei Punkte, die zusammengehören. Erstens: Jede schreibende Operation braucht eine Transaktion — die Annotation heißt hier wie im Jakarta-Standard. Zweitens wandert die Schemapflege zu Flyway, mit Skripten an der gewohnten Stelle im Ressourcenverzeichnis.
5:51 Und drittens gibt es eine Einstellung, ob beim Start migriert werden soll. Der letzte Punkt klingt harmlos, ist aber eine Architekturentscheidung: Migration beim Start ist bequem für kleine Dienste und problematisch, sobald mehrere Instanzen gleichzeitig hochfahren. Und für mehrere Instanzen gilt: Eine Migration beim Start braucht eine Absprache, wer sie ausführen darf. Sonst versuchen es beim Hochfahren alle gleichzeitig.
6:17 Drei Zeilen Konfiguration, und die dritte ist die wichtigste: Die Schemaerzeugung durch Hibernate wird ausdrücklich abgeschaltet. Genau das wird gern vergessen, und dann versuchen zwei Mechanismen gleichzeitig, dieselbe Datenbank zu formen. Das Ergebnis ist bestenfalls eine Fehlermeldung und schlimmstenfalls ein Schema, das niemand mehr reproduzieren kann.
6:38 Merken Sie sich als Regel: Genau ein Werkzeug ist für das Schema zuständig. Und die Fußnote zeigt, wie das bei mehreren Datenquellen aussieht — der Name wird einfach eingeschoben. Das Thema Lazy Loading ist kein Quarkus-Thema, aber es wird bei jeder Migration wieder akut, weil sich die Grenzen der Session verschieben. Die Regel bleibt dieselbe: Nachladen braucht eine offene Session, außerhalb bricht es zur Laufzeit.
7:03 Die beiden nächsten Punkte sind Handwerk — gezieltes Mitladen statt einer Abfrage je Zeile, und Blättern statt ganzer Tabellen. Der letzte Punkt ist der wichtigste und wird am seltensten befolgt: Schauen Sie sich die erzeugten Abfragen im Log an. Fünf Minuten Lesen ersetzen eine Stunde Vermutungen. Der erste Punkt ist der eben genannte Doppelzugriff aufs Schema. Der zweite trifft jeden einmal: eine schreibende Methode ohne Transaktion, die erst zur Laufzeit auffällt.
7:30 Der dritte ist ein Verpackungsfehler — die Migrationsskripte fehlen im Image, weil sie außerhalb des Ressourcenverzeichnisses lagen; das merkt man typischerweise beim ersten Start in der Testumgebung. Und der vierte ist der Klassiker schlechthin: Lazy Loading funktioniert im Test, weil dort zufällig eine Session offen ist, und bricht im Endpunkt.
Übung
7:50 In der Übung gehen Sie beide Wege — erst die Kompatibilitätsschicht, dann Panache — und prüfen, ob wirklich dasselbe herauskommt. Der Maßstab dieser Übung ist streng, und das mit Absicht: Alle Abfragen müssen dieselben Ergebnismengen liefern wie vorher. Nicht ähnliche, dieselbe. Dazu gehört ausdrücklich die Sortierung und die Paginierung — zwei Dinge, bei denen Abweichungen lange unentdeckt bleiben, weil die Datenmenge im Test zufällig klein ist.
8:17 Nutzen Sie dieselben Testdaten für beide Varianten, sonst vergleichen Sie zwei verschiedene Welten. Benennen Sie außerdem jedes nicht unterstützte Konstrukt, das Ihnen begegnet, und notieren Sie den gewählten Ersatz. Diese Liste ist später die belastbarste Grundlage, um den Aufwand für die übrigen Dienste hochzurechnen — belastbarer als jede Schätzung aus dem Bauch heraus.
8:39 Der zweite Schritt ist der wichtigste, und er entscheidet über Ihre Aufwandsschätzung: Listen Sie die nicht unterstützten Konstrukte auf und suchen Sie für jedes einen Ersatz. Erst danach wird umgeschrieben. Im vierten Schritt kommt Flyway hinzu, und im selben Atemzug wird die Schemaerzeugung durch Hibernate abgeschaltet.
8:57 Und der fünfte Schritt ist der, den man gern überspringt: das erzeugte SQL vergleichen. Zwei Abfragen können dasselbe Ergebnis liefern und trotzdem völlig unterschiedlich teuer sein. Der erste Punkt ist die häufigste Selbsttäuschung: Es wird die Anzahl der Zeilen verglichen, nicht ihre Reihenfolge — und eine geänderte Sortierung fällt bei zwölf Testdatensätzen niemandem auf.
9:18 Zweitens die Versuchung, alles in einem Schritt umzustellen; dann gibt es keinen Zwischenstand, zu dem man zurückkehren kann. Drittens werden neue Testdaten erzeugt, womit der Vergleich mit dem Ausgangsstand wertlos wird. Und viertens fällt das fehlende Sperrverhalten erst im Lasttest auf — wenn Sie einen haben. Wenn nicht, fällt es in Produktion auf.
Lieber mit Trainer? Dieses Modul ist Teil unserer Team-Schulungen — mit Übungen, Ihrem eigenen Code und Fragen, die ein Video nicht beantwortet. Mehr erfahren →