JPA @Transient поля очищаются до вызова метода @PreUpdate - PullRequest
13 голосов
/ 05 августа 2010

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

Итак, у меня есть что-то вроде этого:

@Transient
private String password;

private String hashedPassword;

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

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

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

(кстати, я использую EclipseLink 2.0.0, если это имеет какое-либо значение)

Ответы [ 2 ]

5 голосов
/ 19 марта 2014

Я решил это, установив обновляемый и вставляемый в значение false в поле «переходный», поэтому в вашем случае это будет:

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

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

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

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

3 голосов
/ 10 августа 2010

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