Вот спецификация JPA 2.0:
Обратные вызовы PreUpdate и PostUpdate выполняются до и после операций обновления базы данных для данных объекта соответственно. Эти операции с базой данных могут происходить во время обновления состояния объекта или могут происходить во время сброса состояния в базу данных (что может быть в конце транзакции).
Помните, что @ PreUpdate всегда будет запускаться для всех транзакций чтения / записи из-за FlushMode для транзакций чтения / записи и никогда не для транзакций только для чтения (из-за FlushMode.NEVER)
Без OSIV
Когда вы звоните updateUser
, тогда у вас есть транзакция чтения / записи (внешняя) из-за @Transactional
.
Теперь findByName
является транзакционным, но помечается как только для чтения (по умолчанию все средства поиска только для чтения ). Текущая транзакция приостановлена, и выполняется новая readonly . Вот почему (1) строка не вызывает @Preupdate
.
. После этого текущая транзакция чтения / записи возобновляется (save
не только для чтения), и @Preupdate
срабатывает.
С OSIV
В этом случае существует только одна транзакция чтения / записи, связанная с текущим запросом. findByName
выполняется в транзакции чтения / записи, поэтому (1) строка вызывает @ Preupdate