Весняні дані: "Видалити за" підтримується?


99

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

Чи підтримує Spring JPA deleteByName як видалення? Будь-який вказівник цінується.

З повагою та подякою

Відповіді:


184

Застаріла відповідь (Весняні дані 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 Downvote, тому що це вже не хороша відповідь. Може, видалити його? Одним з недоліків stackoverflow є обробка змін / виправлень версій, пов’язаних із відповідними бібліотеками.
Бен Джордж

1
@webgeek, я раніше вирішував це питання DELETE FROM x WHERE id = ?1 or parent_id = ?1. До речі, переконайтеся, що у вас немає типу parent__id(у вас є подвійний низький тире за наміром?). Чому ви все ж використовуєте варіант власного запиту?
Андрій Атапін

4
Навіть я використовую 1.7.4, для успішного видалення потрібна анотація @Transactional над методом запиту
gokhansari

40
Як правило, у додатку у вас будуть @ клас обслуговування / методи, які будуть викликати сховища. І публічними методами @ Service повинні бути методи, позначені @ Transactional, оскільки транзакції засновані на Use Case. Значить, випадок використання потребує повного фіксації або відкоту. Не кожен окремий метод репозиторію. Отже, БУДЬ ЛАСКА, НЕ використовуйте @ Transactional для методів репозиторію. Але про методи служби, які використовують репозиторій.
користувач1567291

1
Зробити @Transactional на репо, означає всередині сервісу, якщо ви дзвоните репо кілька разів, кожен з них матиме різну транзакцію, тому відкат у межах 1 запиту. Якщо ви надаєте послуги на рівні обслуговування, вся ваша функція буде відмовлятися за будь-якої помилки.
P

78

Виведення запитів видалення за допомогою заданого імені методу підтримується, починаючи з версії 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 способи: -

Перший спеціальний запит

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

2-й запит JPA методом

List<User> deleteByLastname(String lastname);

Коли ви перейдете із запитом методом (2-й спосіб), то спочатку викличете дзвінок

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
Дякую за інформацію!
цікаво1

2

Якщо ви будете використовувати заздалегідь визначені методи видалення, як безпосередньо передбачено весною JPA, то нижче два запити будуть виконуватися рамкою.

  • Спочатку збирайте дані (наприклад, id та інший стовпець), використовуючи команду Execute select query із видаленням запиту, де пункт.

  • то після отримання результатуНабір першого запиту, для всіх id (один за одним) буде виконуватися другий запит на видалення

    Примітка. Це не оптимізований спосіб для вашої програми, оскільки буде виконано багато запитів для одного запиту на видалення 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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.