Как стать автором
Обновить

Комментарии 25

Знаете, что из всего этого следует? Что в отличие от хард, soft deletion - это бизнес-операция, а не техническая операция хранилища. И решать ее нужно, соответственно, на бизнес-, а не на техническом уровне. С той же статьей, например, комментарии к софтово-удаленной статье можно таким же образом софтово-удалить.

100% согласен

С той же статьей, например, комментарии к софтово-удаленной статье можно таким же образом софтово-удалить.

Если потом восстановить софтово-удаленную статью, то не получится отличить комментарии, которые софтово-удалены вместе со статьей от комментариев, которые софтово-удалены сами по себе по кнопке "удалить комментарий".

...значит, нужен гипер-флаг, говорящий о том, что удаление прилетело сверху, и computed-колонка, которая объединяет эти флаги по ИЛИ )

значит, нужен гипер-флаг,

Конечно, нужен. Лишь подтверждение тому, что у задачи отсутствует чисто-техническое решение, как вы верно заметили в своём изначальном комментарии.

Зачем удалять комментарии каскадом не пойму. Статья удалена софтово. К ней есть джойны у комментариев. Состояние комментариев однозначно (видим, не видим потому что удалена статья, не видим потому что удален комментарий), зачем его портить? По какому хочешь критерию по такому и тащишь.

Более того, если их удалять, то

нужен гипер-флаг

Оверинженер в действии :)

Вообще, с помощью софтделишена решать задачу data recovery идея не очень. Ведь нужно знать контекст удаления. Плюс, потом базу будем мигрировать вместе с удаленными сущностиями, а ведь иногда поля могут становиться обязательными... И чем заполнять удаленные данные? Де-факто мы их трогать вообще после удаления не должны... Вобщем одни минусы. Почему знаю, я так делал :). Потом переписал на жесткое удаление с сохранинием фактически удаляемых данных в монгу + отедльная логика восстановления в зависимости от версии модели.

Если пользоваться мягким удалением, то для многих может быть неожиданностью, что не работат стандартные хуки связанные с delete - preRemove/postRemove, при это в postUpdate нельзя понять контекст что запись была мягко удалена.

Если у вас разработка на триггерах - ну что ж, вы, самураи, сами выбрали этот путь.

не работат стандартные хуки связанные с delete

Как и CascadeType.REMOVE

В 99% soft-delete не нужен. От него геморроя больше, чем профита.

Хочется иметь возможность восстановить удалённые записи? Envers в помощь. Да, придётся сделать дополнительные приседания, но это хоть как-то управляемо и настраиваемо.

Есть два типа людей: те, которые думают, что 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 вообще отлично работает взде, кроме... кэша :).

Да и он на фетчинг никак не влияет, только на запросы. Полезная штука)

За все время так и не нашел аргументов за ленивое удаление, особенно если оно настроено для всего подряд. За пять лет пригодилось может один или два раза и то для дебага.

Мягкое удаление делаем ручками. Часто вместо него можно сделать галочку Активный, а на странице списка объектов — фильтр, который по умолчанию показывает только активные. Если юзер по ошибке удалил — он может сам восстановить объект (вернуть галочку), не нужно просить запускать SQL апдейт для этого. И можно отредактировать уже «удалённый» объект при необходимости.

А как это выглядит в спрингдате?

Везде приходится писать @Query и перегружать стандартные методы. По другому не выйдет.

Спрингдату не используем, везде вручную добавляем условия по active = true

Самый неочевидный факт в мягком удалении, это то зачем оно нужно. Часто под мягким удалением подразумемвают замену системной delete операции. По этому и появляется нужда в системном подходе к решению. На самом же деле это не системная, а бизнес операция. Спустить бизнес уровень на системный всегда чревато серьезными последствиями. Особенно такими что многние подходы и библиотеки станут неприменимы.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий