Проще говоря, модификация deleted
не включена в PostDeleteEvent
.
Hibernate создает состояние, которое включается в PostDeleteEvent
один раз, в начале рабочего процесса удаления сущности. Для традиционного использования это имеет смысл, поскольку выполняемый оператор является DELETE
, поэтому строка не изменяется.
Загадка здесь - @SQLDelete
просто заменяет сгенерированный оператор DELETE
, который персистент использует для использования, на собственную версию. Вообще говоря, предоставляемый вами SQL может быть любым, если он является синтаксически верным DML.
Что Hibernate не знает, так это то, что в данном случае SQL для замены является UPDATE
. Следовательно, повторная синхронизация состояния моментального снимка персистера не происходит, и состояние события не изменяется после того, как персистер выполнил оператор удаления SQL, а когда срабатывает обратный вызов с удалением post , им все еще предоставляется состояние в начале рабочего процесса удаления объекта.
С учетом сказанного, Энверс записывает REVTYPE=2
(он же DEL
) в таблицу аудита. Поэтому, если вам нужна временная метка удаления, вы все равно можете получить ее из таблицы Envers REVINFO
.
UPDATE
Другая идея заключается в том, чтобы использовать два столбца, а не один столбец. Вместо использования метки времени в качестве индикатора мягкого удаления, используйте битовый флаг
@Entity
@Audited
@SQLDelete("UPDATE person SET deleted = true WHERE id = ?")
@Where(clause = "deleted is NULL or deleted != true")
public class Person {
@NotAudited
private boolean deleted;
private OffsetDateTime deleteTime;
@PreRemove
public void onPreRemove() {
this.deleteTime = ...;
}
}
Здесь я использую @PreRemove
, чтобы установить значение времени удаления, которое затем должно быть передано в PostDeleteEvent
в Envers и позволить Hibernate управлять битовым полем. А поскольку поле deleted
никогда не указывается в состоянии события, я пометил его как @NotAudited
, чтобы исключить его из схемы аудита.