Какое должно быть имя метода, чтобы генерировался запрос DELETE FROM ... WHERE date < :1?

Есть Entity:

@Entity
@Getter
@Setter
@NoArgsConstructor
public class Keys {
    private @Id
    @GeneratedValue(generator = "UUID")
    @GenericGenerator(
            name = "UUID",
            strategy = "org.hibernate.id.UUIDGenerator"
    )
    String id;

    private @Lob
    java.security.KeyPair keyPair;
    private Calendar expirationDate;

    public Keys(java.security.KeyPair keyPair, Calendar expirationDate) {
        this.keyPair = keyPair;
        this.expirationDate = expirationDate;
    }
}

И репозиторий:

public interface KeysRepository extends JpaRepository<Keys, String> {
}

Необходимо выполнять операцию удаления всех Keys, у которых expirationDate раньше переданного времени. Очевидно, что этой задаче соответствует запрос DELETE FROM Keys WHERE expirationDate < :1. Но при добавлении в интерфейс методов deleteAllByExpirationDateBefore(Calendar date), deleteKeysByExpirationDateBefore(Calendar date), deleteByExpirationDateBefore(Calendar date) логируются запросы:

Hibernate: 
    select
        keys0_.id as id1_0_,
        keys0_.expiration_date as expirati2_0_,
        keys0_.key_pair as key_pair3_0_ 
    from
        keys keys0_ 
    where
        keys0_.expiration_date<?
Hibernate: 
    delete 
    from
        keys 
    where
        id=?

Т.е., вместо простого DROP FROM Keys WHERE expiration_date < ? выполняется сначала select всех удовлетворяющих, а после этого они удаляются по одному (delete from keys where id=?).

Вопрос: Как сделать так, чтобы при вызове метода выполнялся запрос delete from keys where expiration_date < ?? Без использования аннотации @Query.


Ответы (1 шт):

Автор решения: Roman Konoval

Автоматически сгенерированные методы deleteBy* всегда сначала читают данные отдельным запросом, а потом удаляют по одному.

Причина этого описана в документации, а именно, это сделано для того, чтоб можно было вызвать обработчики @PreRemove и таким образом, чтоб поведение этого способа удаления было таким же как и delete.

derived delete query is a shortcut for running the query and then calling CrudRepository.delete(Iterable users) on the result and keeping behavior in sync with the implementations of other delete(…) methods in CrudRepository

Так что без использования @Query + @Modifying не обойтись (имя метода в этом случае не имеет значения):

@Modifying
@Query("delete from Keys k where k. expirationDate < :date")
void deleteKeysByExpirationDateBefore(@Param("date") String date);
→ Ссылка