Как повторно реализовать методы запроса по примеру JpaRepository, чтобы игнорировать мягко удаленные объекты - PullRequest
0 голосов
/ 27 февраля 2019

В текущем проекте у меня есть AuditableEntity абстрактный класс, от которого наследуется большинство других сущностей.AuditableEntity указанные столбцы createdAt, updatedAt (со значениями, автоматически заполняемыми аннотациями @CreatedDate & @LastModifiedDate Spring), а также столбец 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, но является ли это правильным местом для вдохновения?Как будет выглядеть общая версия этих двух методов (которая будет автоматически игнорировать записи, удаленные без ошибок)?

...