Domänenobjekte als IDs verursachen einige komplexe / subtile Probleme:
Serialisierung / Deserialisierung
Wenn Sie Objekte als Schlüssel speichern, wird die Serialisierung des Objektdiagramms äußerst kompliziert. Sie erhalten stackoverflowFehler , wenn aufgrund der Rekursion eine naive Serialisierung JSON oder XML zu tun. Sie müssen dann einen benutzerdefinierten Serializer schreiben, der die tatsächlichen Objekte konvertiert, um ihre IDs zu verwenden, anstatt die Objektinstanz zu serialisieren und die Rekursion zu erstellen.
Übergeben Sie Objekte zur Typensicherheit, speichern Sie jedoch nur IDs. Anschließend können Sie eine Zugriffsmethode verwenden, die die zugehörige Entität beim Aufruf verzögert lädt. Das Caching der zweiten Ebene kümmert sich um nachfolgende Anrufe.
Subtile Referenzlecks:
Wenn Sie Domänenobjekte in Konstruktoren verwenden, wie Sie sie dort haben, erstellen Sie Zirkelverweise, bei denen es sehr schwierig ist, Speicher für Objekte zurückzugewinnen, die nicht aktiv verwendet werden.
Ideale Situation:
Undurchsichtige IDs vs int / long:
Ein idsollte ein vollständig undurchsichtiger Bezeichner sein, der keine Informationen darüber enthält, was er identifiziert. Es sollte jedoch eine gewisse Bestätigung bieten, dass es sich um eine gültige Kennung in seinem System handelt.
Rohe Typen brechen dies:
int, longUnd Stringsind die am häufigsten rohen Typen für Bezeichner in RDBMS - System verwendet. Es gibt eine lange Geschichte praktischer Gründe, die Jahrzehnte zurückreichen, und alle sind Kompromisse, die entweder zum Sparen spaceoder zum Sparen timeoder zu beidem passen .
Sequentielle IDs sind die schlimmsten Straftäter:
Wenn Sie eine sequentielle ID verwenden, packen Sie standardmäßig zeitliche semantische Informationen in die ID. Welches ist nicht schlecht, bis es verwendet wird. Wenn Leute anfangen, Geschäftslogik zu schreiben, die die semantische Qualität der ID sortiert oder filtert, dann schaffen sie eine Welt voller Schmerzen für zukünftige Betreuer.
String Felder sind problematisch, weil naive Designer Informationen in den Inhalt packen, normalerweise auch zeitliche Semantik.
Diese machen es unmöglich, auch ein verteiltes Datensystem zu erstellen, da 12437379123es global nicht eindeutig ist. Die Wahrscheinlichkeit, dass ein anderer Knoten in einem verteilten System einen Datensatz mit derselben Nummer erstellt, ist so gut wie garantiert, wenn Sie genügend Daten in einem System erhalten.
Dann beginnen Hacks, es zu umgehen, und das Ganze verwandelt sich in einen Haufen dampfenden Chaos.
Wenn Sie große verteilte Systeme ( Cluster ) ignorieren , wird dies zu einem Albtraum, wenn Sie versuchen, die Daten auch mit anderen Systemen zu teilen. Besonders wenn das andere System nicht unter Ihrer Kontrolle ist.
Sie haben genau das gleiche Problem, wie Sie Ihre ID global eindeutig machen können.
UUID wurde aus einem Grund erstellt und standardisiert:
UUIDkann unter allen oben aufgeführten Problemen leiden, je nachdem, welche VersionSie verwenden.
Version 1Verwendet eine MAC-Adresse und Zeit, um eine eindeutige ID zu erstellen. Dies ist schlecht, da es semantische Informationen über Ort und Zeit enthält. Das ist an sich kein Problem, wenn naive Entwickler sich für die Geschäftslogik auf diese Informationen verlassen. Dadurch werden auch Informationen verloren, die bei Eindringversuchen ausgenutzt werden könnten.
Version 2Die Verwendung eines Benutzers UIDoder eines GIDDomians UIDoder GUIanstelle der Zeit Version 1davon ist genauso schlimm wie Version 1für Datenlecks und das Risiko, dass diese Informationen in der Geschäftslogik verwendet werden.
Version 3ist ähnlich, ersetzt jedoch die MAC-Adresse und die Zeit durch einen MD5Hash eines Arrays byte[]von etwas, das definitiv eine semantische Bedeutung hat. Es gibt keinen Datenverlust, über den Sie byte[]sich Sorgen machen müssen. Der Datenverlust kann nicht behoben werden UUID. Dies gibt Ihnen eine gute Möglichkeit, UUIDInstanzformulare und externe Schlüssel deterministisch zu erstellen .
Version 4 basiert nur auf Zufallszahlen, was eine gute Lösung ist, es enthält absolut keine semantischen Informationen, aber es ist nicht deterministisch wiederherstellbar.
Version 5ist genauso wie Version 4aber verwendet sha1statt md5.
Domänenschlüssel und Transaktionsdatenschlüssel
Ich bevorzuge Domänenobjekt-IDs, wenn ich sie aus technischen Gründen verwende Version 5oder Version 3wenn ich sie nicht verwenden darf Version 5.
Version 3 eignet sich hervorragend für Transaktionsdaten, die möglicherweise auf viele Computer verteilt sind.
Verwenden Sie eine UUID, es sei denn, Sie sind durch Speicherplatz eingeschränkt:
Sie sind garantiert eindeutig, geben Daten aus einer Datenbank aus und laden sie erneut in eine andere. Sie mussten sich nie um doppelte IDs sorgen, die tatsächlich auf unterschiedliche Domänendaten verweisen.
Version 3,4,5 sind völlig undurchsichtig und so sollten sie sein.
Sie können eine einzelne Spalte als Primärschlüssel mit einem UUIDund dann zusammengesetzte eindeutige Indizes für einen natürlichen zusammengesetzten Primärschlüssel haben.
Speicher muss auch nicht sein CHAR(36). Sie können das UUIDFeld in einem nativen Byte- / Bit- / Zahlenfeld für eine bestimmte Datenbank speichern, solange es noch indizierbar ist.
Erbe
Wenn Sie unformatierte Typen haben und diese nicht ändern können, können Sie sie dennoch in Ihrem Code abstrahieren.
Wenn Sie einen Version 3/5von UUIDIhnen verwenden, können Sie das Class.getName()+ String.valueOf(int)als a übergeben byte[]und einen undurchsichtigen Referenzschlüssel haben, der neu erstellt und deterministisch ist.