2010-08-05 18 views
12

Tengo una clase de Entidad de usuario para la que estoy intentando hacer el hash de contraseñas. Pensé que la manera más fácil de hacer esto sería crear un campo de contraseña anotado con @Transient y un campo de contraseña hash que se establece justo antes de que el objeto se persista con un método anotado con @PrePersist y @PreUpdate.JPA @Se han borrado los campos de acceso antes de que se llame al método @PreUpdate

Así que tener algo como esto:

@Transient 
private String password; 

private String hashedPassword; 

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

Esto funciona perfectamente bien cuando una entidad se conserva. El campo de contraseña todavía se establece cuando hashPassword se llama, y ​​se calcula y almacena un valor para hashedPassword.

Sin embargo, no ocurre lo mismo con una actualización: incluso si se establece un nuevo valor para la contraseña justo antes de fusionar la entidad, el campo es nulo cuando se llama hashPassword. ¿Por qué es esto? ¿No deberían los valores de los campos transitorios quedarse por lo menos hasta que la entidad persista?

(estoy usando EclipseLink 2.0.0 por cierto, si hace alguna diferencia)

+3

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

+0

Sí, ese es exactamente el mismo comportamiento (ver sección ** 3.2.4.1 Fusión del estado de la entidad independiente * * de la especificación para la semántica de fusión). –

Respuesta

5

He resuelto esto estableciendo actualizable und insertable en false en el campo "transitoria", por lo que en su caso sería:

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

tanto se requiere una tabla @column (lo cual es feo) pero nunca se completará (lo cual fue importante en mi caso por razones de seguridad).

Probé contra Hibernate 4.3.4.Final y funcionó para mí. El valor de campo fue utilizable en mis métodos EntityLister @PrePersist y @PreUpdate, pero no se almacenó en la base de datos.

Espero que ayude a alguien que tenga problemas similares.

3

Como se mencionó en la respuesta anterior, esto es por diseño en la especificación. EclipseLink contiene un evento (postMerge) que no forma parte de la especificación de JPA que debe invocarse en el punto correcto del ciclo. En EclipseLink 2.1, la clase del Adaptador de eventos del descriptor se puede registrar utilizando la anotación @EventListeners regular, pre 2.1 tendrá que agregar el par usando la API nativa de EclipseLink.

@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

Por alguna razón, si hago esto, se llama al método de Meme pero se ignoran mis métodos PrePersist y PreUpdate. ¿Alguna idea? – javydreamercsw

Cuestiones relacionadas