Comments 25
Знаете, что из всего этого следует? Что в отличие от хард, soft deletion - это бизнес-операция, а не техническая операция хранилища. И решать ее нужно, соответственно, на бизнес-, а не на техническом уровне. С той же статьей, например, комментарии к софтово-удаленной статье можно таким же образом софтово-удалить.
100% согласен
С той же статьей, например, комментарии к софтово-удаленной статье можно таким же образом софтово-удалить.
Если потом восстановить софтово-удаленную статью, то не получится отличить комментарии, которые софтово-удалены вместе со статьей от комментариев, которые софтово-удалены сами по себе по кнопке "удалить комментарий".
...значит, нужен гипер-флаг, говорящий о том, что удаление прилетело сверху, и computed-колонка, которая объединяет эти флаги по ИЛИ )
значит, нужен гипер-флаг,
Конечно, нужен. Лишь подтверждение тому, что у задачи отсутствует чисто-техническое решение, как вы верно заметили в своём изначальном комментарии.
Зачем удалять комментарии каскадом не пойму. Статья удалена софтово. К ней есть джойны у комментариев. Состояние комментариев однозначно (видим, не видим потому что удалена статья, не видим потому что удален комментарий), зачем его портить? По какому хочешь критерию по такому и тащишь.
Более того, если их удалять, то
нужен гипер-флаг
Оверинженер в действии :)
Вообще, с помощью софтделишена решать задачу data recovery идея не очень. Ведь нужно знать контекст удаления. Плюс, потом базу будем мигрировать вместе с удаленными сущностиями, а ведь иногда поля могут становиться обязательными... И чем заполнять удаленные данные? Де-факто мы их трогать вообще после удаления не должны... Вобщем одни минусы. Почему знаю, я так делал :). Потом переписал на жесткое удаление с сохранинием фактически удаляемых данных в монгу + отедльная логика восстановления в зависимости от версии модели.
Если пользоваться мягким удалением, то для многих может быть неожиданностью, что не работат стандартные хуки связанные с delete - preRemove/postRemove
, при это в postUpdate
нельзя понять контекст что запись была мягко удалена.
Есть два типа людей: те, которые думают, что soft-delete - это генианльно и те, которые его уже выпилили из проекта.
Отличная статья, для тех кто еще не ошибся. Называть это "мягким удалением" на мой взгляд неправильно. Например для статьи, ее можно не "мягко-удалять", а "скрыть", "заархивировать", "распубликовать". И тогда все встанет на свои места.
Для @Fetch(FetchMode.JOIN) @ManyToOne(fetch = FetchType.EAGER) Фильтрация @Where включается, если в join добавлено условие фильтрации @JoinColumnOrFormula по полю, не являющемуся id.
Пример:
модель
@Entity
@Table(name = "post_reference")
public class PostEagerJoinReference {
@Id
private Long id;
@Fetch(FetchMode.JOIN)
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumnOrFormula(column = @JoinColumn(name = "post_id", referencedColumnName = "id"))
@JoinColumnOrFormula(formula = @JoinFormula(value = "any", referencedColumnName = "title"))
private Post post;
}
@Entity
@Table(name = "post")
@Where(clause = "deleted = false")
public class Post implements Serializable {
@Id
private Long id;
@Column(name = "title")
private String title;
@Column(name = "deleted")
private boolean deleted = false;
}
на запрос
entityManager.find(PostEagerJoinReference.class, 1L);
генерируется запрос:
select
posteagerj0_.id as id1_1_0_,
posteagerj0_.post_id as post_id2_1_0_,
any as formula2_0_,
post1_.id as id1_0_1_,
post1_.deleted as deleted2_0_1_,
post1_.title as title3_0_1_
from
post_reference posteagerj0_
left outer join
post post1_
on posteagerj0_.post_id=post1_.id
and any=post1_.title
and (
post1_.deleted = false
)
where
posteagerj0_.id=?
В качестве поля не являющимся id можно использовать delete = true, тогда фильтр `deleted = false` на JOIN задвоится.
Кстати еще это приведет вот к такому багу https://hibernate.atlassian.net/browse/HHH-7668, который решается добавлением на сущность implements Serializable
.
Спасибо! Но это не отменяет того, что поведение не должно зависить от типа FetchType. А потом в Spring Data кто-то определяет EntityGraph и все снова летит к чертям...
Да тут все плохо, но с этим уже как-то можно жить с hibernate. Мне в проекте по другой причине нужно было добавить дефолтную фильтрацию. Пробовал @Where, @Filter, @Loader. И везде свои дыры и баги.
@Filter вообще отлично работает взде, кроме... кэша :).
За все время так и не нашел аргументов за ленивое удаление, особенно если оно настроено для всего подряд. За пять лет пригодилось может один или два раза и то для дебага.
Самый неочевидный факт в мягком удалении, это то зачем оно нужно. Часто под мягким удалением подразумемвают замену системной delete операции. По этому и появляется нужда в системном подходе к решению. На самом же деле это не системная, а бизнес операция. Спустить бизнес уровень на системный всегда чревато серьезными последствиями. Особенно такими что многние подходы и библиотеки станут неприменимы.
Мягкое удаление в Hibernate: неочевидные факты