Хорошо, я сделал несколько тестов, и это то, что я нашел, и что мое мнение по этому делу (им используется JPA 2.1).
Единственный раз, операция merge()
может вызывать прослушиватель событий, когда он вызывается на новом объекте, который еще не сохранен. Затем он действует как операция persist()
, и вызываются классы аннотированных @PrePersist
. Это правильное поведение в спецификации:
В PrePersist
и PreRemove
методы обратного вызова для данного объекта до того, как соответствующие EntityManager
persist
и remove
операции для этого объекта выполняются. Для объектов, к которым была применена операция слияния , и приводит к созданию новых управляемых экземпляров , методы обратного вызова PrePersist будут вызваны для управляемого экземпляра после того, как состояние объекта было скопировано на него.
Теперь, что вы делаете, это изменение уже существующего объекта, и единственным вызывающим абонентом является @PreUpdate/@PostUpdate
. Хотя в спецификации у вас есть:
Обратите внимание, что это зависит от реализации, как для того, происходят ли PreUpdate и PostUpdate обратные вызовы, когда объект сохраняется и впоследствии были внесены изменения в одной транзакции или когда объект является модифицирована и впоследствии удаляется в рамках одной транзакции. Переносные приложения не должны полагаться на такое поведение
По моему мнению, вы следуете сценарию «сущность изменена и впоследствии удалена». Удалено значение из PersistenceContext
, когда оно отсоединено в вашем случае, и в этом случае поведение непредсказуемо. После некоторых тестов я подтверждаю, что метод слушателя не вызывается в таком случае.
Я не мог найти никакой дополнительной конфигурации, которая может каким-либо образом привести в действие это поведение. Надеюсь, что помогает.
Можете ли вы приложить свой транзакционный метод, когда выполняете все операции, включая слияние? Может пролить некоторый свет на вещи. –