Подтвердить что ты не робот

Поля JPA @Transient очищаются до вызова метода @PreUpdate

У меня есть класс 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.

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

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

4b9b3361

Ответ 1

Я решил это, установив updatable und insertable в false в поле "переходный", поэтому в вашем случае это будет:

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

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

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

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

Ответ 2

Как упоминалось в приведенном выше ответе, это по дизайну в спецификации. 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();
    }
}