Spring Data: «Удалить по» поддерживается?


101

Я использую Spring JPA для доступа к базе данных. Я могу найти такие примеры, как findByName и countByName, для которых мне не нужно писать какую-либо реализацию метода. Я надеюсь найти примеры удаления группы записей по какому-либо условию.

Поддерживает ли Spring JPA удаление, подобное deleteByName? Любой указатель приветствуется.

С уважением и благодарностью.

Ответы:


187

Устаревший ответ (Spring Data JPA <= 1.6.x) :

@Modifyingаннотация на помощь. Однако вам нужно будет указать свое собственное поведение SQL.

public interface UserRepository extends JpaRepository<User, Long> {
    @Modifying
    @Query("delete from User u where u.firstName = ?1")
    void deleteUsersByFirstName(String firstName);
}

Обновить:

В современных версиях Spring Data JPA (> = 1.7.x) запрос вывода для delete, removeи countопераций доступно.

public interface UserRepository extends CrudRepository<User, Long> {

    Long countByFirstName(String firstName);

    Long deleteByFirstName(String firstName);

    List<User> removeByFirstName(String firstName);

}

2
@AndreyAtapin Голосовать против, потому что это уже не лучший ответ. Может, удалить? Одним из недостатков stackoverflows является обработка изменений версий / исправлений ошибок, связанных с рассматриваемыми библиотеками.
Бен Джордж

1
@webgeek, я раньше эту проблему решал с помощью DELETE FROM x WHERE id = ?1 or parent_id = ?1. Кстати, убедитесь, что у вас нет типа parent__id(у вас намеренно есть двойной низкий рывок?). Но почему вы используете собственный вариант запроса?
Андрей Атапин

4
Даже я использую 1.7.4, аннотация @Transactional необходима выше метода запроса для успешного удаления
гохансари

40
Как правило, в приложении у вас будут классы / методы @ Service, и они будут вызывать репозитории. И общедоступные методы @ Service должны быть методами, отмеченными @ Transactional, поскольку транзакции основаны на сценариях использования. Это означает, что для варианта использования необходимо выполнить полную фиксацию или откат. Не каждый отдельный метод репозитория. ПОЖАЛУЙСТА, НЕ ИСПОЛЬЗУЙТЕ @ Transactional в методах репозитория. Но о методах Сервиса, использующих репозиторий.
user1567291 05

1
Создание @Transactional в репо означает внутреннюю службу, если вы вызываете репо несколько раз, каждая из них будет иметь транзакцию diff, поэтому откат в пределах 1 запроса. Если вы предоставляете услуги на уровне обслуживания, вся ваша функция будет отменена при любой ошибке.
P Satish Patro

79

Создание запросов на удаление с использованием данного имени метода поддерживается, начиная с версии 1.6.0.RC1 Spring Data JPA. Ключевые слова removeи deleteподдерживаются. В качестве возвращаемого значения можно выбрать количество или список удаленных объектов.

Long removeByLastname(String lastname);

List<User> deleteByLastname(String lastname);

7

Если вы посмотрите на исходный код Spring Data JPA и, в частности, на PartTreeJpaQueryкласс, вы увидите, что он пытается создать экземпляр PartTree. Внутри этого класса следующее регулярное выражение

private static final Pattern PREFIX_TEMPLATE = Pattern.compile("^(find|read|get|count|query)(\\p{Lu}.*?)??By")

должен указать, что разрешено, а что нет.

Конечно, если вы попытаетесь добавить такой метод, вы на самом деле увидите, что он не работает, и получите полную трассировку стека.

Я должен отметить, что я использовал версию 1.5.0.RELEASESpring Data JPA


6

2 способа: -

1-й пользовательский запрос

@Modifying
@Query("delete from User where firstName = :firstName")
void deleteUsersByFirstName(@Param("firstName") String firstName);

Второй запрос JPA по методу

List<User> deleteByLastname(String lastname);

Когда вы переходите с запросом по методу (2-й способ), он сначала выполняет вызов get

select * from user where last_name = :firstName

Затем он загрузит его в список. Затем он будет вызывать удаление идентификатора один за другим.

delete from user where id = 18
delete from user where id = 19

Сначала получить список объектов, затем цикл для удаления идентификаторов по одному

Но, 1-й вариант (индивидуальный запрос),

Это всего лишь один запрос. Он удалит везде, где существует значение.

Пройдите и по этой ссылке https://www.baeldung.com/spring-data-jpa-deleteby


1
Спасибо за информацию!
curious1 05

2

Если вы будете использовать предопределенные методы удаления, которые напрямую предоставлены Spring JPA, то платформа будет выполнять два запроса ниже.

  • Сначала соберите данные (например, идентификатор и другой столбец), используя выполнение запроса выбора с предложением где удалить запрос.

  • затем после получения resultSet первого запроса будут выполняться вторые запросы на удаление для всех идентификаторов (один за другим)

    Примечание. Это не оптимизированный способ для вашего приложения, потому что многие запросы будут выполняться для одного запроса на удаление MYSQL.

Это еще один оптимизированный способ удаления кода запроса, потому что только один запрос на удаление будет выполняться с использованием указанных ниже настраиваемых методов.



@NamedNativeQueries({

@NamedNativeQuery(name = "Abc.deleteByCreatedTimeBetween",
            query = "DELETE FROM abc WHERE create_time BETWEEN ?1 AND ?2")
    ,

    @NamedNativeQuery(name = "Abc.getByMaxId",
            query = "SELECT max(id) from abc")
})

@Entity
public class Abc implements Serializable {

}

@Repository
public interface AbcRepository extends CrudRepository {

    int getByMaxId();

    @Transactional
    @Modifying
    void deleteByCreatedTimeBetween(String startDate, String endDate);
}

1

Будьте осторожны при использовании производного запроса для пакетного удаления. Это не то, что вы ожидаете: DeleteExecution


Здравствуй. Если вы указываете на RBAR (строка за мучительной строкой), не могли бы вы добавить это к своему ответу? (и я буду голосовать за). Я как бы догадываюсь, на что вы здесь указываете.
granadaCoder

0

Да, метод deleteBy поддерживается. Для его использования необходимо аннотировать метод с помощью @Transactional.


0

вот мои 2 цента. Вы также можете использовать собственные запросы, например:

@Modifying
@Query(value="delete from rreo r where r.cod_ibge = ?1 and r.exercicio= ?2", nativeQuery = true)
void deleteByParameters(Integer codIbge, Integer exercicio);
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.