在当前项目中,我有一个AuditableEntity
抽象类,大多数其他实体都从该抽象类继承。 AuditableEntity
指定了createdAt
,updatedAt
列(其值通过Spring的@CreatedDate
和@LastModifiedDate
注释自动填充)以及deletedAt
列,由于Spring不支持(据我所知)开箱即用的软件删除,因此需要手动执行。 AuditableEntity
看起来像这样:
@Getter
@Setter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
@JsonIgnoreProperties(
value = {"createdAt", "updatedAt", "deletedAt"},
allowGetters = true
)
public abstract class AuditableEntity<T> extends IdentifiableEntity<T> implements Serializable {
@CreatedDate
@Column(name = "dba_ins_ymd", nullable = false, updatable = false)
private Instant createdAt;
@LastModifiedDate
@Column(name = "dba_upd_ymd", nullable = false)
private Instant updatedAt;
@Column(name = "dba_del_ymd")
private Instant deletedAt;
}
然后,由于有不同的StackOverflow答案,我有一个SoftDeleteJpaRepository
接口(从JpaRepository
继承),该接口会自动忽略软删除的条目,如下所示:
@NoRepositoryBean
public interface SoftDeleteJpaRepository<T extends AuditableEntity<ID>, ID> extends JpaRepository<T, ID> {
@Override
@Transactional(readOnly = true)
@Query("select e from #{#entityName} e where e.deletedAt is null")
List<T> findAll();
@Override
@Transactional(readOnly = true)
@Query("select e from #{#entityName} e where e.deletedAt is null order by ?1")
List<T> findAll(Sort sort);
@Override
@Transactional(readOnly = true)
@Query("select e from #{#entityName} e where e.id in ?1 and e.deletedAt is null")
List<T> findAllById(Iterable<ID> ids);
@Override
default void deleteInBatch(Iterable<T> entities) {
throw new NotImplementedException("Not implemented yet");
}
@Override
default void deleteAllInBatch() {
throw new NotImplementedException("Not implemented yet");
}
@Override
@Transactional(readOnly = true)
@Query("select e from #{#entityName} e where e.id = ?1 and e.deletedAt is null")
T getOne(ID id);
@Override
@Transactional(readOnly = true)
@Query("select e from #(#entityName) e where e.deletedAt is null")
default Page<T> findAll(Pageable pageable) {
throw new NotImplementedException("Not implemented yet");
}
@Override
@Transactional(readOnly = true)
@Query("select e from #{#entityName} e where e.id = ?1 and e.deletedAt is null")
Optional<T> findById(ID id);
@Override
default boolean existsById(ID id) {
return getOne(id) != null;
}
@Override
@Transactional(readOnly = true)
@Query("select count(e) from #{#entityName} e where e.deletedAt is null")
long count();
@Override
@Transactional
@Query("update #{#entityName} e set e.deletedAt = current_timestamp where e.id = ?1")
@Modifying
void deleteById(ID id);
@Override
@Transactional
default void delete(T entity) {
deleteById(entity.getId());
}
@Override
@Transactional
default void deleteAll(Iterable<? extends T> entities) {
entities.forEach(entity -> deleteById(entity.getId()));
}
@Override
@Transactional
@Query("update #{#entityName} e set e.deletedAt = current_timestamp")
@Modifying
void deleteAll();
@Query("select e from #{#entityName} e where e.deletedAt is not null")
@Transactional(readOnly = true)
List<T> findSoftDeleted();
}
基本上,到目前为止,混合的@Query
注释和一些default
实现的混合。
最后,这是一个问题:对于我的一些用例,我还需要使用示例查询,因此我需要以类似的方式调整<S extends T> List<S> findAll(Example<S> example)
和<S extends T> Page<S> findAll(Example<S> example, Pageable pageable)
方法,这样他们将自动忽略deletedAt
列中包含任何值的条目。但坦率地说,我不知道从哪里开始或如何做。
我尝试查找Spring如何实现这些方法,但我只能找到QueryByExampleExecutor
接口中的方法名称。 IDEA表明该方法的唯一实现是在SimpleJpaRepository
中,但这是从中获取灵感的正确地方吗?这两种方法的通用版本(会自动忽略软删除的条目)会是什么样子?