JPA软删除存储库+审核

时间:2019-10-08 15:55:26

标签: java spring jpa spring-data-jpa

我需要实现JPA软删除存储库,并同时支持对几列的JPA审核。 目前,我已经通过EL和@ Query + @ Modifying注释实现了Soft Delete存储库:

    @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 个答案:

答案 0 :(得分:1)

如果您使用的是Hibernate,则可以自定义在remove上执行的SQL,这样就不必发出delete语句,而是将active标志设置为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;
}

这样做还有一个好处,即级联删除在使用批量删除时不会按预期执行。

答案 1 :(得分:0)

更新: 我决定使用覆盖的默认删除存储库方法来将活动标志更新为'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);
        }
    }