Обновление сущности в Spring Data JPA и JPARepository: пошаговый гайд
Быстрый ответ
Если ваша задача — обновить сущность с помощью Spring Data JPA, то вы можете сделать это следующим образом: сначала воспользуйтесь findById
для поиска нужной сущности, затем измените требуемые поля и вызовите метод save()
, чтобы сохранить внесённые изменения.
YourEntity entity = repository.findById(id).orElseThrow(EntityNotFoundException::new); // Поиск сущности по Id
entity.setSomeField(newValue); // Внесение изменений
repository.save(entity); // Сохранение внесённых изменений
Примечательно, что JPA самостоятельно отслеживает изменения и обновляет поля по окончании транзакции.
Подробнее о методе save()
Метод repository.save(entity)
работает таким образом: Spring Data JPA выбирает между merge()
и persist()
, основываясь на наличии ID у сущности. Если ID задан, то будет произведено обновление, в случае отсутствия ID — вставка новой записи.
"Единица работы" JPA
Паттерн Единица работы в контексте JPA обеспечивает применение всех изменений в рамках одной транзакции единовременно при её завершении. Это значительно упрощает управление сущностями в Spring Data JPA.
Транзакции
Чтобы обновление данных было максимально эффективным, оно должно быть выполнено в контексте транзакции. При помощи аннотации @Transactional
от Spring вы задаёте границы транзакции, что позволяет методу save()
осуществить все необходимые операции.
Визуализация
Обновление сущности в Spring Data JPA можно визуализировать следующим образом — как изменение пункта назначения у пассажира поезда:
Билет ДО обновления:
+--------------------------+
| Имя: Алиса 🙍♀️ |
| Направление: Париж 🗼 |
+--------------------------+
Алиса изменяет своё направление:
Passenger passenger = repository.findById(1L).orElseThrow(EntityNotFoundException::new); // Определение местонахождения Алисы
passenger.setDestination("Rome"); // Изменение маршрута на Рим 🍕
repository.save(passenger); // Алиса отправляется в Рим!
Билет ПОСЛЕ обновления:
+--------------------------+
| Имя: Алиса 🙍♀️ |
| Направление: Рим 🏛️ |
+--------------------------+
Важно понимать:
💾 repository.save(entity)
— изменяет пункт назначения для Алисы.
🔍 repository.findById(id)
— находит текущий билет Алисы.
Пользовательские запросы на обновление
Иногда функциональности JPA может не хватать, и приходится написать собственный запрос на обновление. Для этого используйте аннотацию @Query
в сочетании с @Modifying
.
@Modifying
@Query("update YourEntity y set y.field = :value where y.id = :id") // Установка новых значений
int updateTheField(@Param("value") FieldType newValue, @Param("id") Long id); // ID обновляемой записи
Количество затронутых записей возвращается в виде int
.
Производительность и эффективность
Чтобы повысить производительность, старайтесь избегать лишних соединений и жадной загрузки. Если требуется обновить большое количество данных, лучше это делать на уровне сервиса, оставив репозиторий только для доступа к данным.
Полезные материалы
- Spring Data JPA :: Spring Data JPA — Подробное руководство по сохранению и обновлению сущностей с помощью Spring Data JPA.
- Difference Between save() and saveAndFlush() in Spring Data JPA | Baeldung — Сравнение методов
save()
иsaveAndFlush()
. - How does the entity version property work when using JPA and Hibernate – Vlad Mihalcea — Детальное изучение аннотации
@Version
на примерах от эксперта. - Getting Started | Accessing Data with JPA — Руководство для начинающих по работе с JPA и Spring.
- Hibernate ORM User Guide — Руководство по отслеживанию изменений и сбросу состояния в Hibernate.
- Software Testing Tutorial – Learn Unit Testing and Integration Testing – YouTube — Обзор тестирования функционала обновления и удаления в Spring Boot JPA.