我需要实现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
注释不是一个选择,因为有可能查询软删除的实体。
能否请您提供其他可能的解决方案?
答案 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);
}
}