Ich migriere ein Altsystem, um Hibernate 3 zu verwenden. Es generiert derzeit eigene Kennungen. Um mit dem, was das System derzeit tut, fortzufahren, versuche ich, es etwas besser zu überarbeiten. Wie würde ich meine eigene Klasse (die Annotationen verwendet) spezifizieren, die die benutzerdefinierten IDs zurückgibt, wenn ein Einfügen stattfindet?
Etwas wie:
%Vor% Wo die Klasse Foo
über eine Methode verfügt, die den Bezeichner generiert.
Momentan rufe ich nur die Methode setId(String id)
manuell an, hoffe aber auf einen besseren Weg, um mit dieser Situation umzugehen.
Ich glaube nicht, dass es eine vordefinierte Unterstützung für das Generieren benutzerdefinierter IDs mit benutzerdefinierten Anmerkungen unter Verwendung der reinen JPA-2-API gibt. Wenn Sie jedoch eine anbieterspezifische API verwenden möchten, ist der Job ziemlich einfach. Beispielbeispiel
Um providerunabhängig zu sein, probiere einen der folgenden Tricks aus ....
IdGeneratorHolder
%Vor%Allgemeine IdGenerator-Schnittstelle
%Vor%Spezifischer IdGenerator - Produkt-ID-Generator
%Vor%Legen Sie jetzt die generierte ID entweder in in no-arg-Konstruktor ODER in der @ PrePersist-Methode fest.
Produkt.java
%Vor% Im obigen Beispiel sind alle IDs vom selben Typ, d.h. java.lang.String
. Wenn die persistenten Entitäten IDs unterschiedlicher Typen haben .....
IdGenerator.java
%Vor%CustomId.java
%Vor%Item.java
%Vor%Sie können auch Ihre benutzerdefinierte Anmerkung verwenden ...
CustomIdGenerator.java
%Vor%IdStrategy.java
%Vor%IdGeneratorHolder.java
%Vor%Noch eine Sache .... Wenn wir ID in der @ PrePersist-Methode setzen, kann die equals () -Methode nicht auf das ID-Feld (d. h. Ersatzschlüssel) zurückgreifen, wir müssen den Business / Natural-Schlüssel zur Implementierung der equals () -Methode verwenden. Aber wenn wir das ID-Feld auf einen eindeutigen Wert (uuid oder "app-uid" innerhalb der Anwendung) im no-arg-Konstruktor setzen, hilft es uns, die equals () -Methode zu implementieren.
%Vor%Wenn wir oder jemand anders (absichtlich oder versehentlich) die annullierte Methode @PrePersist mehr als einmal aufruft, wird die "eindeutige ID geändert !!!" Daher ist das Setzen von ID in einem Konstruktor ohne Argumente vorzuziehen. ODER, um dieses Problem zu beheben, setzen Sie einen nicht Null-Check ...
%Vor%Wenn wir die ID-Generation in a einfügen Nein-Arg-Konstruktor, würde das nicht Beim Laden von Objekten tritt ein Problem auf aus der Datenbank? weil überwintern Ruft den No-Arg-Konstruktor auf bestehende Ids verursachen neu generiert
Ja, du hast Recht, ich habe diesen Teil vermisst. :( Eigentlich wollte ich dir sagen: - In meiner Anwendung ist jedes Entity-Objekt einer Organisationseinheit zugeordnet, also habe ich eine abstrakte Superklasse mit zwei Konstruktoren erstellt, und jede Entität (außer Organisation) erweitert diese Klasse.
%Vor%Der no-arg-Konstruktor ist für den JPA-Provider, wir rufen nie den arg-Konstruktor auf, sondern den anderen organisationsbasierten Konstruktor. Wie du siehst. ID wird in organisationsbasiertem Konstruktor zugewiesen. (Ich habe diesen Punkt wirklich verpasst, als ich die Antwort geschrieben habe, tut mir Leid).
Sehen Sie, ob Sie diese oder ähnliche Strategie in Ihrer Anwendung implementieren können.
Die zweite Option war die Verwendung der @ PrePersist Annotation. Ich habe das reingelegt und die Methode wurde nie getroffen und gab mir eine Ausnahme, die besagt, dass ich gebraucht habe um die ID manuell festzulegen. ist da etwas anderes sollte ich tun?
Idealerweise sollte der JPA-Provider @PrePersist-Methoden aufrufen (eine in der Klasse deklarierte Methode und auch alle anderen Methoden, die in Superklassen deklariert sind), bevor das Entitätsobjekt persistiert wird. Kann Ihnen nicht sagen, was falsch ist, es sei denn, Sie zeigen etwas Code und Konsole.
Sie können.
Implementiere zuerst org.hibernate.id.IdentifierGenerator
Dann müssten Sie es in einer Mapping-XML-Datei abbilden. Ich konnte keine Möglichkeit finden, dies mit Anmerkungen zu tun:
%Vor% Verwenden Sie schließlich @GeneratedValue(generator="identifier-name")
Beachten Sie, dass dies für den Ruhezustand spezifisch ist (nicht JPA)
Update: Ich habe mir die Quellen von Hibernate angeschaut und es scheint an einer Stelle, nachdem der Kurzname nicht aufgelöst werden konnte, Hibernate zu versuchen, Class.forName(..)
aufzurufen. Der Parameter dort heißt strategy
. Also, hier ist, was Sie versuchen:
generator
-Attribut @GenericGenerator
strategy
-Attribut (mit einem beliebigen Namen) Lass mich wissen, welche (falls überhaupt) funktioniert