2010-08-05 8 views
12

aufgerufen wird. Ich habe eine User Entity-Klasse, für die ich ein Passwort-Hashing durchführen möchte. Ich dachte, dass dies am einfachsten wäre, ein mit @Transient annotiertes Kennwortfeld und ein Hash-Kennwortfeld zu erstellen, das unmittelbar vor der Speicherung des Objekts mit einer mit @PrePersist und @PreUpdate annotierten Methode festgelegt wird.JPA @Transient-Felder werden gelöscht, bevor die @PreUpdate-Methode

So habe ich so etwas wie diese:

@Transient 
private String password; 

private String hashedPassword; 

@PrePersist 
@PreUpdate 
private void hashPassword() { 
    if(password != null) { 
     hashedPassword = PasswordHasher.hashPassword(password); 
    } 
} 

Die perfekt funktioniert gut, wenn ein Unternehmen beibehalten wird. Das Kennwortfeld wird immer noch von der Zeit festgelegt, in der hashPassword aufgerufen wird, und ein Wert für hashedPassword wird berechnet und gespeichert.

Das gleiche gilt jedoch nicht für ein Update - selbst wenn ein neuer Wert für das Kennwort kurz vor dem Zusammenführen der Entität festgelegt wird, ist das Feld zu dem Zeitpunkt null, zu dem hashPassword aufgerufen wird. Warum ist das? Sollten die Werte transienter Felder nicht mindestens so lange bestehen bleiben, bis die Entität bestehen bleibt?

(Ich bin mit Eclipselink 2.0.0 btw, wenn es einen Unterschied macht)

+3

möglich dupe: http://stackoverflow.com/questions/2581665/jpa-transient-information-lost-on-create –

+0

Ja, das ist genau das gleiche Verhalten (siehe Abschnitt ** 3.2.4.1 Verschmelzung von getrennten Entity State * * der Spezifikation für die Semantik der Zusammenführung). –

Antwort

5

Ich löste dies durch aktualisierbar und einführbar auf false auf der "transient" Feldeinstellung, so in Ihrem Fall sein würde:

@Column(name = "password", insertable = false, updatable = false) 
private String password; 

Deshalb eine Tabelle @column wird benötigt (was ziemlich hässlich ist), aber sie wird niemals gefüllt (was in meinem Fall aus Sicherheitsgründen wichtig war).

Ich habe gegen Hibernate 4.3.4.Final getestet und es hat für mich funktioniert. Der Feldwert war in meinen EntityLister @ PrePersist- und @ PreUpdate-Methoden verwendbar, wurde jedoch nicht in der Datenbank gespeichert.

Hoffe, dass jeder hilft, der ähnliche Probleme hat.

3

Wie in der obigen Antwort erwähnt, ist dies von Design in der spec. EclipseLink enthält ein Ereignis (PostMerge), das nicht Teil der JPA-Spezifikation ist und am richtigen Punkt im Zyklus für Sie aufgerufen werden sollte. In EclipseLink 2.1 Die Descriptor Event Adapter-Klasse kann mit der regulären Annotation @EventListeners registriert werden, vor Version 2.1 müssen Sie die native API von EclipseLink hinzufügen.

@EntityListeners({ 
    a.b.MyEventListener.class, 
}) 

package a.b; 

import org.eclipse.persistence.descriptors.DescriptorEvent; 
import org.eclipse.persistence.descriptors.DescriptorEventAdapter; 

public class MyEventListener extends DescriptorEventAdapter { 

    public void postMerge(DescriptorEvent event) { 
     //event.getSession(); 
     //event.getObject(); 
     //event.getOriginalObject(); 
    } 
} 
+0

Aus irgendeinem Grund, wenn ich diese postMere-Methode wird aufgerufen, aber meine PrePersist und PreUpdate-Methoden werden ignoriert. Irgendeine Idee? – javydreamercsw

Verwandte Themen