Ich habe drei Arten von Primärschlüsseln für Tabellen:
INT
automatisch generierter Primärschlüssel, der AUTO_INCREMENT
Kapazität vom Datenbankhersteller (MySQL) CHAR(X)
Primärschlüssel zum Speichern eines benutzerlesbaren Werts als Schlüssel (wobei X eine Zahl und 50 & lt; = X & lt; = 60) Es gibt auch eine Gruppe von Feldern, die vorhanden sein können (oder nicht):
INT
field. VARCHAR(60)
field und lastUpdatedBy, VARCHAR(60)
field (es gibt mehr Felder, aber diese decken ein einfaches Beispiel ab). Einige Beispiele für oben:
Vor diesem Hintergrund muss ich eine generische Gruppe von Klassen erstellen, die diese Anforderungen unterstützen und CRUD-Operationen mit Hibernate 4.3 und JPA 2.1 ermöglichen.
Hier ist mein aktuelles Modell (Getter / Setter vermieden, das Codebeispiel zu verkürzen):
%Vor% Ich teste gerade Save-Instanzen von Table1
und Table2
. Ich habe den folgenden Code:
Beim Versuch, Table2
zu speichern, schlägt es fehl und der folgende Fehler wird angezeigt:
Die Fehlermeldung ist offensichtlich, weil ein CHAR(X)
-Feld keinen Standardwert hat und nicht haben wird (AFAIK). Ich habe versucht, die Generierungsstrategie in GenerationType.AUTO
zu ändern und habe die gleiche Fehlermeldung erhalten.
Wie kann ich diese Klassen umbauen, um diese Anforderungen zu unterstützen? Oder noch besser, wie könnte ich eine Generierungsstrategie bereitstellen, die vom Schlüssel der Entität abhängt, die ich speichere, die automatisch generiert oder von mir bereitgestellt werden kann?
Beteiligte Technologien:
Hinweis: Das oben Genannte kann (und wird wahrscheinlich) geändert werden, um für andere Implementierungen von JPA 2.1 wie EclipseLink unterstützt zu werden.
Sie können diese erzwungene abgeleitete Klasse "umgehen", um eine Methode zu implementieren, die sicherstellt, dass die ID zugewiesen ist, und diese Methode mit @PrePersist annotieren. Sie können eine Standardimplementierung für Klassen bereitstellen, für die die ID automatisch generiert wird.
Etwas wie:
%Vor%Habe das nicht versucht, aber laut Hibernates API sollte das nicht kompliziert sein, indem man eine benutzerdefinierte Implementierung von IdentityGenerator .
Es gibt generate-Methode-gets und -Objekte, für die Sie den Wert generieren, so dass Sie den Typ des ID-Felds überprüfen und den entsprechenden Wert für Ihren Primärschlüssel zurückgeben können.
%Vor%Wenn Sie dies einfach als Ihre Generierungsstrategie verwenden:
%Vor% Für Hibernate 4 sollten Sie IdentifierGenerator
Schnittstelle.
Wie oben für Hibernate akzeptiert, sollte es immer noch möglich sein, es generischer für jeden "jpa-kompatiblen" Provider zu erstellen. Laut JPA-API in GeneratedValue Annotation können Sie Ihren benutzerdefinierten Generator bereitstellen. Dies bedeutet, dass Sie den Namen Ihres benutzerdefinierten Generators angeben können, und Sie sollten diesen Generator für jeden jpa-Provider implementieren.
Dies würde bedeuten, dass Sie BaseEntity mit folgender Anmerkung annotieren müssen:
%Vor%Jetzt müssen Sie einen benutzerdefinierten Generator mit dem Namen "my-custom-generator" für jeden jpa-Anbieter registrieren, den Sie verwenden möchten.
Für Hibernate wird dies durch @GenericGenerator Annotation, wie zuvor gezeigt, durchgeführt (das Hinzufügen von @GenericGenerator(name="my-custom-generator", strategy="my.package.DynamicGenerator"
zu BaseEntity
class auf id
field oder BaseEntity
class level sollte ausreichen).
In EclipseLink sehe ich, dass Sie dies über GeneratedValue Annotation erreichen können Registrierung über SessionCustomizer:
%Vor%Jeder Anbieter muss eine Möglichkeit zur Registrierung des ID-Generators angeben. Daher müssen Sie für jeden Provider eine eigene Generierungsstrategie implementieren und registrieren, wenn Sie alle unterstützen möchten.
Vererbungshierarchien kämpfen mit ORM. Halten Sie die Dinge also einfach und bleiben Sie der Datenbankimplementierung ein wenig näher. Ordnen Sie dafür keine Hierarchie von abstrakten Oberklassen zu, sondern binden Sie annotierte POJOs für Teile von gemeinsamen Spalten ein. Sie können sich auch im restlichen Code als als nützlich erweisen .
Erstellen Sie @Embeddable
classes für die freigegebenen Felder und machen Sie die Klasse für Ihre zusammengesetzte ID @Embeddable
ebenfalls.
Die einfachste Version Ihrer Implementierungsklassen sieht dann so aus:
%Vor%Für die String ID, keine automatische Generierung:
%Vor% Und die zusammengesetzte ID als @EmbeddedId
:
Als zusätzlichen Vorteil können Sie mehrere dieser Merkmale mischen und anpassen, wenn Sie möchten, da Sie nicht mehr durch die Vererbungsstruktur eingeschränkt sind.
(Sie können jedoch die Hierarchie beibehalten, die Getter und Setter sowie Standarddelegaten enthält, wenn der vorhandene Code davon abhängt und / oder davon profitiert.)
Tags und Links java jpa mysql hibernate hibernate-4.x