2010-08-05 6 views
12

У меня есть класс User Entity, для которого я пытаюсь выполнить хэширование пароля. Я думал, что самый простой способ сделать это - создать поле пароля, аннотированное с помощью поля @Transient и хэшированного пароля, которое устанавливается непосредственно перед тем, как объект сохраняется с помощью метода, аннотированного с помощью @PrePersist и @PreUpdate.JPA @Transient поля, очищаемые до метода @PreUpdate, называются

Так что у меня что-то вроде этого:

@Transient 
private String password; 

private String hashedPassword; 

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

Это отлично работает, когда объект сохранялось. Поле пароля по-прежнему устанавливается по времени, когда вызывается hashPassword, и вычисляется и сохраняется значение для hashedPassword.

Однако это не относится к обновлению - даже если новое значение для пароля установлено перед объединением объекта, поле равно null на момент, когда вызывается hashPassword. Почему это? Должны ли значения переходных полей придерживаться, по крайней мере, до тех пор, пока сущность не будет сохранена?

(я использую EclipseLink 2.0.0 Кстати, если это делает никакой разницы)

+3

Возможный обман: http://stackoverflow.com/questions/2581665/jpa-transient-information-lost-on-create –

+0

Да, это то же самое поведение (см. Раздел ** 3.2.4.1 Слияние отдельного состояния сущности * * спецификации для семантики слияния). –

ответ

5

Я решил эту проблему, установив обновляемый унд вставляться ложь о "переходном" поле, так что в вашем случае это будет:

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

Поэтому требуется таблица @column (что довольно уродливо), но она никогда не будет заполнена (что было важно в моем случае по соображениям безопасности).

Я протестировал против Hibernate 4.3.4.Final, и это сработало для меня. Значение поля использовалось в моих методах EntityLister @PrePersist и @PreUpdate, но не было сохранено в базе данных.

Надеюсь, что это поможет любому, у кого есть подобные проблемы.

3

Как указано выше в ответе, это дизайн в спецификации. EclipseLink содержит событие (postMerge), которое не является частью спецификации JPA, которое должно быть вызвано в правой части цикла для вас. В EclipseLink 2.1 Класс адаптера событий дескриптора может быть зарегистрирован с использованием обычной аннотации @EventListeners, pre 2.1 вам нужно будет добавить четный, используя собственный API 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

По какой-то причине, если я делаю этот метод postMere, но мои методы PrePersist и PreUpdate игнорируются. Есть идеи? – javydreamercsw

Смежные вопросы