简体   繁体   English

JPA 软删除存储库 + 审计

[英]JPA Soft Delete Repository + Auditing

I need to implement JPA Soft Delete repository and support JPA auditing for several columns at the same time.我需要实现 JPA 软删除存储库并同时支持 JPA 审计多个列。 For now, I've implemented Soft Delete repository via EL and @Query+@Modifying annotations:目前,我已经通过 EL 和 @Query+@Modifying 注释实现了软删除存储库:

    @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.但是对于这样的实现,审计列不会更新,因为如果我正确理解, @Query注释不会触发任何生命周期回调方法。

@Where annotation on the Entity level is not an option because there is the need to have a possibility to query soft deleted entities. @Where实体级别的注释不是一个选项,因为需要有可能查询软删除的实体。

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.如果您使用的是 Hibernate,那么您可以自定义在删除时执行的 SQL,这样就不会发出删除语句,而是将活动标志设置为 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.在这种情况下,您将调用EntityManager#remove (通过 Spring 数据的存储库抽象),然后生命周期侦听器将按预期执行。

@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.更新:我决定 go 使用覆盖的默认删除存储库方法将活动标志更新为“false”并通过常见的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);
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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