简体   繁体   中英

JPA Soft Delete Repository + Auditing

I need to implement JPA Soft Delete repository and support JPA auditing for several columns at the same time. For now, I've implemented Soft Delete repository via EL and @Query+@Modifying annotations:

    @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();

But with such implementation audit columns are not updated because if I correctly understand, @Query annotation doesn't trigger any Lifecycle Callback methods.

@Where annotation on the Entity level is not an option because there is the need to have a possibility to query soft deleted entities.

Could you please help with any other possible solutions?

If you are using Hibernate then you can customise the SQL executed on remove so that rather than issuing a delete statement it sets the active flag to false. In this scenario you would then be invoking EntityManager#remove (via Spring Data's repository abstraction) and lifecycle listeners would then execute as expected.

@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;
}

This has the added advantage that cascading deletes should also execute as expected when they wouldn't when using a bulk delete.

UPDATE: I've decided to go with the overridden default delete repository methods to update an active flag to 'false' and save an entity via common save() method.

    @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);
        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM