Migration auf Hibernate 6.4

31 May 2024

Hibernate ist ein leistungsstarker objektrelationaler Mapper (ORM), der die Lücke zwischen Java-Objekten und relationalen Datenbanken schließt. Hibernate 6 ist im Vergleich zu früheren Versionen ein großer Fortschritt. Es unterstützt moderne JDK- und Jakarta-Spezifikationen für den Datenzugriff.
In diesem Artikel werden nicht alle Details der offiziellen Versionshinweise und Migrationsleitfäden für Hibernate wiederholt. Stattdessen konzentrieren wir uns auf die wichtigsten API-Änderungen, die wir kennen müssen.

Java Version

Mit Version 6.0 erwartet Hibernate ORM Java 11 als Basisversion.

JPA 2.x bis 3.0

JPA 3.0 ändert das Präfix aller Paketnamen von API-Klassen, das Präfix einiger Konfigurationseigenschaften und die Schema-Namespaces für alle XML-basierten Konfigurationsdateien. Ziel dieser Änderungen war es, das Wort „Java“ zu ersetzen, um rechtliche Probleme zu vermeiden.
Das Präfix der Paketnamen und Konfigurationsparameternamen ändert sich von javax.persistence.* zu jakarta.persistence.* [1]

Da Hibernate eine Implementierung der JPA-Spezifikation ist, wechselt Hibernate 6.0 von Java Persistence, wie in den Java EE-Spezifikationen definiert, zu Jakarta Persistence, wie in den Jakarta EE-Spezifikationen definiert.[2]

Einige Leistungsverbesserungen

Positionsbasierter Zugriff auf JDBC-ResultSet:
Hibernate ruft Daten aus JDBC-ResultSets jetzt nach Position statt nach Namen ab. Dies vermeidet unnötige Methodenaufrufe und verbessert möglicherweise die Leistung.

Generiertes SQL:
Hibernate kann jetzt SQL-Abfragen generieren, die Spaltenaliase auslassen und unnötige Verknüpfungen besser bestimmen, was auch zu Leistungsvorteilen führen kann.

SQM-semantisches Abfragemodell:
Die Hauptidee hinter SQM besteht darin, eine einheitliche interne Darstellung sowohl für Criteria API als auch HQL bereitzustellen und SQL-Generierung basierend auf dieser Darstellung durchzuführen.

  • In früheren Hibernate-Versionen wurden Criteria-API-Aufrufe in HQL übersetzt und dann HQL-Strings in SQL umgewandelt. Dies war ein enormer Arbeitsaufwand, der auch String-Manipulationen beinhaltete. Die Unterstützung und Weiterentwicklung erforderte viel Arbeit.
  • Ab Hibernate 6 werden sowohl Criteria-API-Aufrufe als auch HQL-Anweisungen in SQM übersetzt. Anschließend generierte Hibernate SQL basierend auf dieser Datenstruktur. Bei der Implementierung dieser Funktion nahm das Hibernate-Team auch zwei große Änderungen vor:
    • Anstelle von ANTLR2 verwendet Hibernate jetzt den ANTLR4-Parser. Die neue Version bietet mehr Funktionen und hat eine bessere API.
    • Die Hibernate-Criteria-API ist veraltet; stattdessen wird die JPA-Criteria-API verwendet. [3][4]

Implizite Bezeichnersequenz und Tabellenname

Ab Hibernate 6.0 erstellt das Framework eine Sequenz für jede Entitätshierarchie anstelle einer einzelnen Hibernate-Sequenz.

Aufgrund dieser Änderung müssen Benutzer, die zuvor @GeneratedValue(strategy = GenerationStrategy.AUTO) verwendet haben, sicherstellen, dass die Datenbank jetzt Sequenzen für jede Entität mit dem Namen _seq enthält.

Die Standardzuordnungsgröße für solche impliziten Sequenzen hat sich geändert und ist jetzt 50.

HQL-Nullliteralvergleich

In früheren Versionen von Hibernate war es möglich, Ausdrücke mit einem Nullliteral mit den Operatoren = und <>/!= zu vergleichen.

Ab Hibernate 6.3 sollten wir Abfragen migrieren, um stattdessen die Prädikatsyntax „is null“ und „is not null“ zu verwenden.

Verbesserungen beim Speichern von Langtexten

  • Wenn wir Langtext in der Datenbank speichern müssen, könnten wir auf unerwartete Probleme stoßen. Beispielsweise könnte PostgreSQL Probleme mit Transaktionen und Suchen mit dem Operator „like“ haben.
  • Hibernate 6 vereinheitlicht die Definition von Langtextfeldern mithilfe der Annotation @JdbcTypeCode.
  • @Type(type = “text”) sollte durch @JdbcTypeCode(value = SqlTypes.LONGVARCHAR) ersetzt werden, um lange Stringtypen zu definieren.

UNIQUE-Beschränkung für optionale Eins-zu-eins-Zuordnungen

  • Das optionale Attribut in einer Eins-zu-eins-Beziehung gibt an, dass die zugehörige Entität vorhanden sein kann oder nicht. Wenn die zugehörige Entität nicht vorhanden ist, kann die Anwendung trotzdem mit der primären Entität arbeiten. Aus Datenbanksicht bedeutet dies normalerweise, dass Nullwerte in der Fremdschlüsselspalte zugelassen werden, die auf die zugehörige Entität verweist.
  • Seit Hibernate 6.2 Wenn versucht wird, einen Datensatz mit einem Wert einzufügen oder zu aktualisieren, der bereits in einem anderen Datensatz für dieselbe(n) Spalte(n) vorhanden ist, würde dies zu einer Verletzung der Unique-Beschränkung führen!

FROM ist jetzt für UPDATE nicht zulässig

In Hibernate 5 war das optionale Schlüsselwort FROM für Update-Anweisungen wie

update from MyEntity e set e.attr = null

Die Unterstützung hierfür wurde entfernt, um eine bessere Übereinstimmung mit JPQL zu erzielen. Entfernen Sie einfach das Schlüsselwort from aus Ihren vorhandenen Update-Anweisungen.[1]

Standardkonstruktor ohne Argumente

  • Wenn kein anderer Konstruktor definiert ist, wird zur Kompilierzeit automatisch ein Standardkonstruktor ohne Argumente bereitgestellt. Wenn wir jedoch einen parametrisierten Konstruktor definiert haben, müssen wir auch explizit einen Standardkonstruktor bereitstellen (kann entweder öffentlich oder geschützt sein).
  • Um ein Entity-Objekt zu erstellen, muss der JPA-Anbieter einen Konstruktor ohne Argumente aufrufen. Wenn kein Konstruktor ohne Argumente vorhanden ist, führt dies während der Objektinstanziierung zu einer Ausnahme.[5]

@Generated Values

Frühere Versionen von Hibernate ignorierten Annotationen @GeneratedValue, die auf Felder ohne Bezeichner angewendet wurden, stillschweigend.

Ab Hibernate 6.4 ist diese Zuordnung nicht mehr zulässig und es wird eine AnnotationException ausgelöst.

DISTINCT

From Hibernate ORM 6, distinct is always passed to the SQL query. The returning duplicates of entities are now always filtered by Hibernate.

Deprecated Features

  • hibernate.hbm2dll.create_namespaces ist veraltet Sie können stattdessen hibernate.hbm2ddl.create_namespaces oder jakarta.persistence.create-database-schemas verwenden.
  • Einige Konfigurationseigenschaften, die lange Zeit veraltet waren, wurden schließlich aus Konsistenzgründen entfernt. Weitere Informationen finden Sie im Migrationshandbuch.

Unterstützte Dialekte

Werfen Sie einen Blick auf das Dokument „Unterstützte Dialekte“, um zu prüfen, ob es mögliche Upgrades für die Mindestversion der Datenbanken gibt, die den Dialekten zugrunde liegen, die Hibernate derzeit unterstützt.