2017-01-17 4 views
2

Я наблюдал неожиданное поведение в моем проекте JPA.Обратные вызовы жизненного цикла на отдельном объекте, который не вызывается при объединении обратно

В принципе, мои объекты имеют метод их modified() называется на каждом обновлении следующим образом:

@PrePersist 
@PreUpdate 
private void callback() { 
    modified(); // sets a java.util.time.Instant 
} 

, который работает в обычном режиме.

В какой-то момент мне пришлось отделить сущность, внести некоторые изменения, а затем объединить ее; но обратный вызов не вызывается.

Является ли это ошибкой или частью документированной спецификации?

Я использую EclipseLink, если это имеет значение.

EDIT: Отслеживание его до совершенно другой проблемы, которая не имеет отношения к этому вопросу.

+0

Можете ли вы приложить свой транзакционный метод, когда выполняете все операции, включая слияние? Может пролить некоторый свет на вещи. –

ответ

2

Хорошо, я сделал несколько тестов, и это то, что я нашел, и что мое мнение по этому делу (им используется JPA 2.1).

Единственный раз, операция merge() может вызывать прослушиватель событий, когда он вызывается на новом объекте, который еще не сохранен. Затем он действует как операция persist(), и вызываются классы аннотированных @PrePersist. Это правильное поведение в спецификации:

В PrePersist и PreRemove методы обратного вызова для данного объекта до того, как соответствующие EntityManagerpersist и remove операции для этого объекта выполняются. Для объектов, к которым была применена операция слияния , и приводит к созданию новых управляемых экземпляров , методы обратного вызова PrePersist будут вызваны для управляемого экземпляра после того, как состояние объекта было скопировано на него.

Теперь, что вы делаете, это изменение уже существующего объекта, и единственным вызывающим абонентом является @PreUpdate/@PostUpdate. Хотя в спецификации у вас есть:

Обратите внимание, что это зависит от реализации, как для того, происходят ли PreUpdate и PostUpdate обратные вызовы, когда объект сохраняется и впоследствии были внесены изменения в одной транзакции или когда объект является модифицирована и впоследствии удаляется в рамках одной транзакции. Переносные приложения не должны полагаться на такое поведение

По моему мнению, вы следуете сценарию «сущность изменена и впоследствии удалена». Удалено значение из PersistenceContext, когда оно отсоединено в вашем случае, и в этом случае поведение непредсказуемо. После некоторых тестов я подтверждаю, что метод слушателя не вызывается в таком случае.

Я не мог найти никакой дополнительной конфигурации, которая может каким-либо образом привести в действие это поведение. Надеюсь, что помогает.

+0

Не для этого перед моим ПК, но отключение, изменение и слияние - все в одной транзакции. (не могу вспомнить, но я думаю, что 'merge()' вызывается с помощью метода TransactionAttribute.REQUIRES_NEW', если это имеет значение?) – Mordechai

+0

И отключение перед любым изменением. – Mordechai

+0

Как я уже сказал, было бы полезно также, чтобы другие пользователи увидели транзакционный код, особенно тот факт, что это не обычный случай с этой новой транзакцией, имеющей место –

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

  • Нет связанных вопросов^_^