JPA Soft Delete Репозиторий + Аудит - PullRequest
0 голосов
/ 08 октября 2019

Мне нужно реализовать репозиторий JPA Soft Delete и поддерживать аудит JPA для нескольких столбцов одновременно. На данный момент я реализовал Soft Delete репозиторий через EL и @ Query + @ Изменение аннотаций:

    @Override
    @Modifying
    @Query("update #{#entityName} e set e.active = false where e.id = ?1")
    void deleteById(UUID id);

    @Override
    default void delete(T entity)
    {
        deleteById(entity.getId());
    }

    @Override
    @Modifying
    @Query("update #{#entityName} e set e.active = false where e.id in ?1")
    void deleteAll(Iterable<? extends T> iterable);

    @Override
    @Modifying
    @Query("update #{#entityName} e set e.active = false")
    void deleteAll();

Но при такой реализации столбцы аудита не обновляются, потому что, если я правильно понимаю, аннотация @Query неинициировать любые методы обратного вызова жизненного цикла.

@Where аннотация на уровне сущности не является опцией, поскольку существует необходимость иметь возможность запрашивать мягко удаленные сущности.

Не могли бы вы помочь слюбые другие возможные решения?

Ответы [ 2 ]

1 голос
/ 08 октября 2019

Если вы используете Hibernate, то вы можете настроить SQL, выполняемый при удалении, чтобы вместо выполнения оператора delete для активного флага было установлено значение false. В этом сценарии вы затем будете вызывать EntityManager#remove (через абстракцию репозитория Spring Data), и слушатели жизненного цикла будут работать так, как ожидалось.

@SQLDelete(sql = "UPDATE someEntity SET active= 0 WHERE id = ?", 
                    check ResultCheckStyle.COUNT)
@Entity
public class SomeEntity{

    //if SomeChildEntity has similar @SqlDelete clause then would be 'deleted' also
    @OneToMany(cascade = CascadeType.REMOVE)
    private Set<SomeChildEntity> children;
}

Это имеет дополнительное преимущество, заключающееся в том, что каскадное удаление также должно выполняться, как и ожидалось, когда не выполнялось массовое удаление.

0 голосов
/ 14 ноября 2019

ОБНОВЛЕНИЕ: Я решил использовать переопределенные методы удаления репозитория по умолчанию, чтобы обновить активный флаг на «ложь» и сохранить объект с помощью обычного save() метода.

    @Override
    default void deleteById(UUID id)
    {
        Assert.notNull(id, "The given id must not be null!");

        Optional<T> entity = this.findById(id);
        entity.ifPresent(this::delete);
    }

    @Override
    default void delete(T entity)
    {
        Assert.notNull(entity, "The entity must not be null!");

        entity.setActive(Boolean.FALSE);
        this.save(entity);
    }

    @Override
    default void deleteAll(Iterable<? extends T> entities)
    {
        Assert.notNull(entities, "The given Iterable of entities must not be null!");

        for (T entity : entities)
        {
            this.delete(entity);
        }
    }

    @Override
    default void deleteAll()
    {
        for (T element : this.findAll())
        {
            this.delete(element);
        }
    }
...