Запустите прослушиватель пользовательских событий Hibernate перед автоматически запускаемыми прослушивателями по умолчанию - PullRequest
8 голосов
/ 30 мая 2011

Я сделал пользовательский прослушиватель событий Hibernate, расширяющий org.hibernate.event.PreInsertEventListener. Пользовательский прослушиватель переопределяет метод onPreInsert и устанавливает поле объекта «Контакт» перед сохранением его в БД с DAO.

Проблема в том, что поле было пустым, прежде чем слушатель присвоил ему значение, и прослушиватели событий гибернации по умолчанию автоматически запускаются ДО моего пользовательского слушателя. Когда они проверяют ddl, они видят в поле ограничение not-null и выдают исключение проверки null, прежде чем позволить моему пользовательскому обработчику событий присвоить полю его значение. (та же проблема возникает при использовании Spring AOP вместо пользовательских прослушивателей hibernate: прослушиватель hibernate по умолчанию выполняется перед моим методом аспекта)

Итак, можно настроить порядок запуска слушателей гибернации, зная, что я использую фабрику весенних сессий?

Спасибо

Ответы [ 2 ]

1 голос
/ 10 июня 2011

У меня есть пример для вас, который создает историю данных для сущности человека. Надеюсь, это поможет.

Мне нужно было сделать вспомогательный интерфейс :

public interface DataHistoryAware {

    public DataHistory getDataHistory();

    public void setDataHistory(DataHistory dataHistory);
}

Это реализация прослушивателя :

public class DataHistoryListener {
   @PrePersist
    public void setCreateDataHistory(DataHistoryAware model) {
        //set creationDate
        DataHistory dataHistory = model.getDataHistory() == null ? new DataHistory() : model.getDataHistory();
        dataHistory.setCreationDate(new Date());
        model.setDataHistory(dataHistory); 
    }
@PostUpdate
    public void setUpdateDataHistory(DataHistoryAware model) {
        DataHistory dataHistory = model.getDataHistory() == null ? new DataHistory() : model.getDataHistory();
        dataHistory.setLastModificationDate(new Date());
        model.setDataHistory(dataHistory);
    }
}

физическое лицо :

@Entity
@EntityListeners(DataHistoryListener.class)
@Table(name="person")
public class Person implements Serializable, DataHistoryAware {

@Column(name = "full_name", length = 255, nullable = false)
    private String fullName;

@OneToOne(cascade = CascadeType.PERSIST)
@JoinColumn(name = "data_history_id", nullable = false)
private DataHistory dataHistory;

public String getFullName() {
        return this.fullName;
    }

    public void setFullName(String fullName) {
        this.fullName = fullName;
    }
public DataHistory getDataHistory() {
        return dataHistory;
    }

    public void setDataHistory(DataHistory dataHistory) {
        this.dataHistory = dataHistory;
    }
}

Эта реализация создает запись истории данных для объекта лица перед сохранением и обновляет ее до слияния. Свойство datahistory имеет ограничение not-null, так что это то же самое, что и ваша проблема со свойством not-null контактного объекта. Надеюсь, это было полезно.

1 голос
/ 07 июня 2011

ИМХО, то, что вы делаете, это излишне. Вы можете достичь того же с помощью Interceptor

Если вы уже знаете это и решили переопределить PreInsetEventListener по некоторым причинам (интересно знать), то вам нужно начать с переопределения стандартных реализаций org.hibernate.event.def.AbstractSaveEventListener. Например, org.hibernate.event.def.DefaultSaveEventListener.

Обратите внимание, что проверка ограничений Nullability и внешнего ключа происходит в AbstractSaveEventListener.performSaveOrReplicate и EntityActions добавляются в очередь действий. Эти действия выполняются во время сброса сеанса, и именно тогда вы получаете вызов к вашему PreInsertEventListener из EntityActions.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...