Weisen Sie einer @id-Eigenschaft einen benutzerdefinierten Bezeichner zu

8

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.

    
digiarnie 24.11.2010, 01:04
quelle

2 Antworten

7

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%

AKTUALISIEREN

  

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.

    
dira 24.11.2010, 09:30
quelle
1

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:

  • Versuchen Sie, den vollqualifizierten Klassennamen als Zeichenfolge im generator -Attribut
  • festzulegen
  • versuchen Sie, die Klasse fqn als Zeichenfolge im @GenericGenerator strategy -Attribut (mit einem beliebigen Namen)
  • zu setzen

Lass mich wissen, welche (falls überhaupt) funktioniert

    
Bozho 24.11.2010 01:39
quelle

Tags und Links