So wählen Sie die ID-Generierungsstrategie bei Verwendung von JPA und Hibernate aus

102

Ich habe den Abschnitt zur ID-Generierung im Hibernate-Referenzhandbuch und "Java-Persistenz mit Hibernate" durchgearbeitet.

Mit Hibernate und JPA zusammen stehen einige Optionen zur Verfügung.

Ich suchte nach einer weiteren Dokumentation zur Auswahl der spezifischen Strategie zur ID-Generierung.

Ich suche auch nach Wendepunkten.

Zum Beispiel wird erwartet, dass die Hilo-Strategie die Konkurrenz reduziert. Ich gehe davon aus, dass mit dieser Wahl ein Kompromiss verbunden sein muss.

Ich möchte über die Kompromisse aufgeklärt werden.

Gibt es Literatur?

Vlad Mihalcea
quelle

Antworten:

92

Die API-Dokumente sind diesbezüglich sehr klar.

Alle Generatoren implementieren die Schnittstelle org.hibernate.id.IdentifierGenerator. Dies ist eine sehr einfache Schnittstelle. Einige Anwendungen können ihre eigenen speziellen Implementierungen bereitstellen. Hibernate bietet jedoch eine Reihe integrierter Implementierungen. Die Verknüpfungsnamen für die integrierten Generatoren lauten wie folgt:

Zuwachs

generiert Bezeichner vom Typ long, short oder int, die nur dann eindeutig sind, wenn kein anderer Prozess Daten in dieselbe Tabelle einfügt. Nicht in einem Cluster verwenden.

Identität

unterstützt Identitätsspalten in DB2, MySQL, MS SQL Server, Sybase und HypersonicSQL. Der zurückgegebene Bezeichner ist vom Typ long, short oder int.

Reihenfolge

verwendet eine Sequenz in DB2, PostgreSQL, Oracle, SAP DB, McKoi oder einen Generator in Interbase. Der zurückgegebene Bezeichner ist vom Typ long, short oder int

Hilo

Verwendet einen Hi / Lo-Algorithmus, um Bezeichner vom Typ Long, Short oder Int effizient zu generieren, wobei eine Tabelle und eine Spalte (standardmäßig hibernate_unique_key bzw. next_hi) als Quelle für Hi-Werte angegeben werden. Der Hi / Lo-Algorithmus generiert Bezeichner, die nur für eine bestimmte Datenbank eindeutig sind.

seqhilo

verwendet einen Hi / Lo-Algorithmus, um Bezeichner vom Typ long, short oder int bei einer benannten Datenbanksequenz effizient zu generieren.

uuid

verwendet einen 128-Bit-UUID-Algorithmus, um Bezeichner vom Typ string zu generieren, die innerhalb eines Netzwerks eindeutig sind (die IP-Adresse wird verwendet). Die UUID wird als Zeichenfolge mit 32 hexadezimalen Ziffern codiert.

Guid

Verwendet eine von der Datenbank generierte GUID-Zeichenfolge unter MS SQL Server und MySQL.

einheimisch

Wählt Identität, Sequenz oder Hilo aus, abhängig von den Funktionen der zugrunde liegenden Datenbank.

zugewiesen

Ermöglicht der Anwendung, dem Objekt eine Kennung zuzuweisen, bevor save () aufgerufen wird. Dies ist die Standardstrategie, wenn kein Element angegeben ist.

wählen

Ruft einen Primärschlüssel ab, der von einem Datenbank-Trigger zugewiesen wurde, indem die Zeile anhand eines eindeutigen Schlüssels ausgewählt und der Primärschlüsselwert abgerufen wird.

fremd

verwendet die Kennung eines anderen zugeordneten Objekts. Es wird normalerweise in Verbindung mit einer Primärschlüsselzuordnung verwendet.

Sequenzidentität

Eine spezielle Strategie zur Sequenzgenerierung, die eine Datenbanksequenz für die tatsächliche Wertgenerierung verwendet, diese jedoch mit JDBC3 getGeneratedKeys kombiniert, um den generierten Bezeichnerwert als Teil der Ausführung der Einfügeanweisung zurückzugeben. Diese Strategie wird nur von Oracle 10g-Treibern unterstützt, die für JDK 1.4 vorgesehen sind. Kommentare zu diesen Einfügeanweisungen sind aufgrund eines Fehlers in den Oracle-Treibern deaktiviert.

Wenn Sie eine einfache Anwendung mit nicht vielen gleichzeitigen Benutzern erstellen , können Sie sich für Inkrement, Identität, Hilo usw. entscheiden. Diese sind einfach zu konfigurieren und benötigten nicht viel Codierung in der Datenbank.

Sie sollten je nach Datenbank eine Reihenfolge oder Anleitung wählen . Diese sind sicher und besser, da die idGenerierung innerhalb der Datenbank erfolgt.

Update: Vor kurzem hatten wir ein Problem mit der Identität, bei dem der primitive Typ (int) behoben wurde, indem stattdessen der Warapper-Typ (Integer) verwendet wurde.

ManuPK
quelle
Vielen Dank für ihre Antwort. Ich habe mir die Dokumente bereits angesehen. Ich suche jedoch nach Gründen, warum Menschen so etwas wie Hilo und Seqhilo verwenden würden. Wann treffen wir diese Wahl? Was sind die Anwendungsfälle für die Auswahl.
Wenn es etwas so Unkompliziertes wie eine Sequenz oder eine Anleitung gibt, kann der Entwickler dann andere Wege wählen.
1
Ich habe meine Antwort aktualisiert. Tatsächlich sind Inkrement, Identität, Hilo usw. einfacher. Sie sind jedoch nicht für Unternehmensanwendungen geeignet. Alle Optionen beizubehalten ist kein Problem, aber stellen Sie sicher, dass Sie die für Sie am besten geeignete verwenden!
ManuPK
Ja. Bisher hatte ich nicht das Privileg, zu stimmen oder zu akzeptieren.
Ich möchte mehr Details erfahren. Wenn Sie Zeit haben, lassen Sie es mich wissen.
45

Grundsätzlich haben Sie zwei Hauptoptionen:

  • Sie können den Bezeichner selbst generieren. In diesem Fall können Sie einen zugewiesenen Bezeichner verwenden .
  • Sie können die @GeneratedValueAnmerkung verwenden, und der Ruhezustand weist Ihnen die Kennung zu.

Für die generierten Bezeichner haben Sie zwei Möglichkeiten:

Für numerische Bezeichner haben Sie drei Möglichkeiten :

  • IDENTITÄT
  • REIHENFOLGE
  • TABELLE

IDENTITY ist nur dann eine gute Wahl, wenn Sie SEQUENCE (z. B. MySQL) nicht verwenden können, da JDBC-Batch-Updates deaktiviert werden .

SEQUENCE ist die bevorzugte Option, insbesondere wenn sie mit einem Bezeichneroptimierer wie pooled oder pooled-lo verwendet wird .

TABLE ist um jeden Preis zu vermeiden, da es eine separate Transaktion verwendet, um die schlecht skalierbaren Sperren für Bezeichner und Zeilenebene abzurufen.

Vlad Mihalcea
quelle
20


Vor einiger Zeit habe ich einen ausführlichen Artikel über Hibernate-Schlüsselgeneratoren geschrieben: http://blog.eyallupu.com/2011/01/hibernatejpa-identity-generators.html

Die Auswahl des richtigen Generators ist eine komplizierte Aufgabe, aber es ist wichtig, so schnell wie möglich zu versuchen, sie richtig zu machen - eine späte Migration kann ein Albtraum sein.

Ein wenig abseits des Themas, aber eine gute Chance, einen Punkt zu erwähnen, der normalerweise übersehen wird, nämlich das Teilen von Schlüsseln zwischen Anwendungen (über API). Persönlich bevorzuge ich immer Ersatzschlüssel und wenn ich meine Objekte mit anderen Systemen kommunizieren muss, lege ich meinen Schlüssel nicht offen (obwohl es sich um einen Ersatzschlüssel handelt) - ich verwende einen zusätzlichen 'externen Schlüssel'. Als Berater habe ich mehr als einmal "großartige" Systemintegrationen mit Objektschlüsseln gesehen (der Ansatz "es ist da, verwenden wir es einfach"), nur um ein oder zwei Jahre später festzustellen, dass eine Seite Probleme mit dem Schlüsselbereich oder etwas anderem hat Die Art, die eine gründliche Migration auf dem System erfordert, um seine internen Schlüssel freizulegen. Wenn Sie Ihren Schlüssel aussetzen, müssen Sie einen grundlegenden Aspekt Ihres Codes externen Einschränkungen aussetzen.

Eyal Lupu
quelle
2

Ich finde diesen Vortrag sehr wertvoll https://vimeo.com/190275665 , in Punkt 3 fasst sie diese Generatoren zusammen und gibt auch einige Leistungsanalysen und Richtlinien, wenn Sie jeden verwenden.

Adelin
quelle
6
Das Video kommt mir sehr bekannt vor.
Vlad Mihalcea