2013-11-07 9 views
6

У меня есть сущность:@PreUpdate не работает с Spring Data JPA

@Entity 
@EntityListeners(MyEntityListener.class) 
class MyEntity{ ... } 

и слушатель:

class MyEntityListener{ 
    @PrePersist 
    @PreUpdate 
    public void doSomething(Object entity){ ... } 
} 

Я использую Spring Data генерироваться DAO для этого объекта (1.4. 1) и EclipseLink. Поведение кода выглядит следующим образом:

MyEntity entity = new Entity(); 
entity = dao.save(entity); // the doSomething() is called here 
// change something it the entity and save it again 
dao.save(entity); // the doSomething() is NOT called here, checked with breakpoint 

проблема уже described by someone in 2009, однако, они не придумали какое-либо решение. Интересно, есть ли у кого-нибудь идеи, как его решить?

+0

Вы уверены, что 'doSomething()' не вызывается вообще во второй раз? Он может быть вызван до совершения транзакции, а не сразу. – axtavt

+0

Вы пытались отсоединить объект до второго сохранения()? –

+0

@AndreiI вы правы, когда я получаю объект 'entity = dao.findOne (entity.getId())' перед сохранением его во второй раз, метод слушателя называется успешно. Пожалуйста, разместите его как ответ, и причина, если вы знаете, что происходит. – fracz

ответ

7

Как вы сказали, метод обратного вызова во второй раз называется, если объект отсоединен или извлечен из базы данных.

Я не могу объяснить это точно, но могу думать о описанном сценарии here, когда не было обнаружено грязных полей перед вторым вызовом save() и, следовательно, обратный вызов @PreUpdate не вызывается. Или это может быть просто ошибка в вашей версии EclipseLink.


UPDATE

В спецификации JPA 2.0 я нашел следующее, что это именно ваше поведение (3.5.2 Семантика методы жизненного цикла обратного вызова для лиц):

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

2

Какова ваша транзакционная настройка вокруг ваших двух разных save()?

Я думаю, что между save()/update()/merge()/persist(), для различного состояния объекта (временный, постоянный, отсоединенный) будет выполняться некоторая разница, операции не совпадают с вы подумали, и ваша аннотация @PrePersist и @PreUpdate не вступили в силу.

+0

У меня есть управление транзакциями Spring, но промывка, похоже, не проблема, потому что, когда я заменяю «save» вызовы на 'saveAndFlush', нет никакой разницы. – fracz

+0

после вашего первого сохранения, объект все еще находится в постоянном состоянии. возможно, saveOrUpdate() может решить вашу проблему. –

+0

'saveOrUpdate()' ни в 'JpaRepository', ни в интерфейсах' CrudRepository'. – fracz

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