Что такое crudrepository для чего нужен как использовать
Метод Spring Data – CrudRepository save()
Узнайте, как сохранять и обновлять сущности в базе данных с помощью Spring Data CrudRepository.
1. Обзор
CrudRepository – это интерфейс данных Spring для общих операций CRUD в репозитории определенного типа. Он предоставляет несколько методов из коробки для взаимодействия с базой данных.
В этом уроке мы объясним, как и когда использовать метод CrudRepository |/save () .
Дальнейшее чтение:
Весенние данные JPA @Query
Spring Data JPA – Производные методы удаления
2. Зависимости
Нам придется добавить Spring Data и H2 зависимости от базы данных в ваш pom.xml файл:
3. Пример применения
Далее, давайте создадим интерфейс CrudRepository для работы с объектом Merchandise :
4. CrudRepository save() для добавления нового экземпляра
Давайте создадим новый экземпляр Merchandise Entity и сохраним его в базе данных с помощью репозитория Inventory :
5. CrudRepository save() для обновления экземпляра
Здесь мы обновили наш исходный объект с новой ценой и сохранили изменения обратно в базу данных.
6. Заключение
В этой краткой статье мы рассмотрели использование метода CrudRepository save (). Этот метод можно использовать для добавления новой записи в базу данных, а также для обновления существующей.
Русские Блоги
В чем разница между интерфейсами CrudRepository и JpaRepository в Spring Data JPA?
What is the difference between CrudRepository and JpaRepository interfaces in Spring Data JPA? В Spring Data JPA CrudRepository с JpaRepository В чем разница между интерфейсами?
When I see the examples on the web, I see them there used kind of interchangeably. Когда я увидел эти примеры в Интернете, я увидел, что там они могут использоваться как взаимозаменяемые. What is the difference between them? В чем разница между ними? Why would you want to use one over the other? Почему вы должны использовать одно вместо другого?
#1-й этаж
#2-й этаж
Their main functions are: Их основные функции:
#3-й этаж
Ken’s answer is basically right but I’d like to chime in on the «why would you want to use one over the other?» Ответ Кена в основном правильный, но я хочу поговорить о том, «Почему вы используете одно вместо другого?» part of your question. Часть вашего вопроса.
Basics Базовый
The common interfaces Универсальный интерфейс
The Spring Data core library ships with two base interfaces that expose a dedicated set of functionalities: Основная библиотека Spring Data поставляется с двумя основными интерфейсами, которые предоставляют набор специализированных функций:
Store-specific interfaces Специфичный для магазина интерфейс
The individual store modules (eg for JPA or MongoDB) expose store-specific extensions of these base interfaces to allow access to store-specific functionality like flushing or dedicated batching that take some store specifics into account. Различные модули хранилища (например, для JPA или MongoDB) предоставляют специфичные для магазина расширения этих базовых интерфейсов, чтобы разрешить доступ к специфичным для магазина функциям, таким как обновление или выделенная пакетная обработка, с учетом некоторых деталей магазина. An example for this is deleteInBatch(…) of JpaRepository which is different from delete(…) as it uses a query to delete the given entities which is more performant but comes with the side effect of not triggering the JPA-defined cascades (as the spec defines it). Примером этого является deleteInBatch(…) из JpaRepository Это отличается от delete(…) Поскольку он использует запрос для удаления заданного объекта, он более производительный, но имеет побочный эффект, заключающийся в том, что не запускается каскад, определенный JPA (как это определено в спецификации).
Custom repository base interfaces Пользовательский базовый интерфейс репозитория
The downside of directly depending on one of the provided base interfaces is two-fold. Недостаток прямого использования одного из базовых интерфейсов двоякий. Both of them might be considered as theoretical but I think they’re important to be aware of: Все они могут считаться теоретическими, но я думаю, что важно отметить:
The solution to both of these downsides is to craft your own base repository interface or even a set of them. Решением этих двух недостатков является создание собственного базового интерфейса репозитория или даже их набора. In a lot of applications I have seen something like this: Во многих приложениях я видел такие вещи:
The repository abstraction allows you to pick the base repository totally driven by you architectural and functional needs. Абстракция репозитория позволяет вам выбрать базовый репозиторий, который полностью зависит от ваших архитектурных и функциональных требований. Use the ones provided out of the box if they suit, craft your own repository base interfaces if necessary. Если они подходят, используйте их из коробки и при необходимости создайте свой собственный базовый интерфейс репозитория. Stay away from the store specific repository interfaces unless unavoidable. Если это не неизбежно, держитесь подальше от интерфейсов репозитория, специфичных для магазина.
#4-й этаж
Summary: Резюме:
PagingAndSortingRepository extends CrudRepository PagingAndSortingRepository расширяет CrudRepository
JpaRepository extends PagingAndSortingRepository JpaRepository расширяет PagingAndSortingRepository
The CrudRepository interface provides methods for CRUD operations, so it allows you to create, read, update and delete records without having to define your own methods. CrudRepositoryИнтерфейс предоставляет методы для операций CRUD, поэтому он позволяет создавать, читать, обновлять и удалять записи без необходимости определять свои собственные методы.
The PagingAndSortingRepository provides additional methods to retrieve entities using pagination and sorting. PagingAndSortingRepositoryПредоставляет другие способы извлечения сущностей с помощью разбиения по страницам и сортировки.
Finally the JpaRepository add some more functionality that is specific to JPA. Наконец, JpaRepositoryБыли добавлены некоторые специфичные для JPA функции.
#5-й этаж
I am learning Spring Data JPA. Я изучаю Spring Data JPA. It might help you: Это может помочь вам:
Русские Блоги
Разница между CrudRepository JpaRepository PagingAndSortingRepository
1. Введение
В этой статье представлены три разных репозитория Spring Data и их функции, включая следующие три:
2. Spring Data Repositories
Из-за отношения наследования между тремя,JpaRepository содержит все API CrudRepository и PagingAndSortingRepository。
Когда нам не нужны функции, предоставляемые JpaRepository и PagingAndSortingRepository, мы можем просто использовать CrudRepository.
Ниже мы используем примеры, чтобы лучше понять API, который они предоставляют.
Сначала создайте объект Product:
Затем выполните операцию запроса продукта по имени:
Таким образом, реализуется метод запроса продукта по имени, и Spring Data Repository автоматически генерирует соответствующую реализацию на основе имени метода.
3. CrudRepository
Первый взгляд CrudRepository Исходный код интерфейса:
Введение в функцию метода:
4. PagingAndSortingRepository
Исходный код интерфейса PagingAndSortingRepository выглядит следующим образом:
Этот интерфейс предоставляет findAll(Pageable pageable) Этот метод является ключом к подкачке.
При использовании Pageable необходимо создать объект Pageable и установить как минимум следующие 3 параметра:
5. JpaRepository
Исходный код интерфейса JpaRepository:
Кратко расскажите о роли каждого метода:
6. Недостатки Spring Data Repositories
Хотя Spring Data Repositories имеет много преимуществ, у них есть и недостатки:
В чем разница между интерфейсами CrudRepository и JpaRepository в Spring Data JPA?
в чем разница между CrudRepository и JpaRepository интерфейсы в Spring Data JPA?
когда я вижу примеры в Интернете,я вижу, что они используются взаимозаменяемо. В чем разница между ними? Почему вы хотите использовать одно над другим?
3 ответов
их основные функции:
ответ Кена в основном прав, но я хотел бы вмешаться в «Почему вы хотите использовать один над другим?- это часть твоего вопроса.
основы
базовый интерфейс, который вы выбираете для своего репозитория, имеет две основные цели. Во-первых, вы позволяете инфраструктуре хранилища данных Spring найти ваш интерфейс и инициировать создание прокси-сервера, чтобы внедрить экземпляры интерфейса в клиенты. Вторая цель состоит в том, чтобы вытащить столько функциональности, сколько необходимо в интерфейс без необходимости объявлять дополнительные методы.
общие интерфейсы
библиотека Spring Data core поставляется с двумя базовыми интерфейсами, которые предоставляют выделенный набор функций:
магазин-специальные интерфейсы
индивидуальные модули магазина (например для JPA или MongoDB) предоставляет расширения хранилища этих базовых интерфейсов, чтобы обеспечить доступ к функциям хранилища, таким как промывка или специальная дозировка, которые учитывают некоторые особенности магазина. Примером этого является deleteInBatch(…) of JpaRepository отличается от delete(…) поскольку он использует запрос для удаления данных сущностей, который более эффективен, но имеет побочный эффект не запуска каскадов, определенных JPA (как определяет его спецификация).
пользовательские базовые интерфейсы репозитория
оборотная сторона сразу в зависимости от одного из обеспеченных низкопробных интерфейсов двухкратна. Оба их можно рассматривать как теоретические, но я думаю, что их важно знать:
решение обоих этих недостатков заключается в создании собственной базы интерфейс репозитория или даже их набор. Во многих приложениях, мы видели что-то вроде этого:
резюме-tl; dr
абстракция репозитория позволяет выбрать базовый репозиторий, полностью управляемый архитектурными и функциональными потребностями. Используйте те, которые предоставляются из коробки, если они подходят, создайте свои собственные базовые интерфейсы репозитория, если это необходимо. Держитесь подальше от интерфейсов хранилища хранилища, если это не неизбежно.
Абстрактный CRUD от репозитория до контроллера: что ещё можно сделать при помощи Spring + Generics
Совсем недавно на Хабре мелькнула статья коллеги, который описал довольно интересный подход к совмещению Generics и возможностей Spring. Мне она напомнила один подход, который я использую для написания микросервисов, и именно им я решил поделиться с читателями.
На выходе мы получаем транспортную систему, для добавления в которую новой сущности нужно будет ограничиться инициализацией одного бина в каждом элементе связки репозиторий-сервис-контроллер.
Сразу ресурсы.
Ветка, как я не делаю: standart_version.
Подход, о котором рассказывается в статье, в ветке abstract_version.
Я собрал проект через Spring Initializr, добавив фреймворки JPA, Web и H2. Gradle, Spring Boot 2.0.5. Этого будет вполне достаточно.
Для начала, рассмотрим классический вариант транспорта от контроллера до репозитория и обратно, лишённый всякой дополнительной логики. Если же Вы хотите перейти к сути подхода, проматывайте вниз до абстрактного варианта. Но, всё же, рекомендую прочитать статью целиком.
Классический вариант.
В ресурсах примера представлены несколько сущностей и методов для них, но в статье пусть у нас будет только одна сущность User и только один метод save(), который мы протащим от репозитория через сервис до контроллера. В ресурсах же их 7, а вообще Spring CRUD / JPA Repository позволяют использовать около дюжины методов сохранения / получения / удаления плюс Вы можете пользоваться, к примеру, какими-то своими универсальными. Также, мы не будем отвлекаться на такие нужные вещи, как валидацию, мапинг dto и прочее. Это Вы сможете дописать сами или изучить в других статьях Хабра.
Domain:
Repository:
Service:
Service (имплементация):
Controller:
У нас получился некий набор зависимых классов, которые помогут нам оперировать сущностью User на уровне CRUD. Это в нашем примере по одному методу, в ресурсах их больше. Этот нисколько не абстрактный вариант написания слоёв представлен в ветке standart_version.
Допустим, нам нужно добавить ещё одну сущность, скажем, Car. Мапить на уровне сущностей мы их друг к другу не будем (если есть желание, можете замапить).
Для начала, создаём сущность.
Потом создаём репозиторий.
Потом имплементация сервиса…… Контроллер………
Да, можно просто скопипастить те же методы (они же у нас универсальные) из класса User, потом поменять User на Car, потом проделать то же самое с имплементацией, с контроллером, далее на очереди очередная сущность, а там уже выглядывают ещё и ещё… Обычно устаёшь уже на второй, создание же служебной архитектуры для пары десятков сущностей (копипастинг, замена имени сущности, где-то ошибся, где-то опечатался. ) приводит к мукам, которые вызывает любая монотонная работа. Попробуйте как-нибудь на досуге прописать двадцать сущностей и Вы поймёте, о чём я.
И вот, в один момент, когда я как раз увлекался дженериками и типовыми параметрами, меня осенило, что процесс можно сделать гораздо менее рутинным.
Итак, абстракции на основе типовых параметров.
Смысл данного подхода заключается в том, чтобы вынести всю логику в абстракцию, абстракцию привязать к типовым параметрам интерфейса, а в бины инжектить другие бины. И всё. Никакой логики в бинах. Только инжект других бинов. Этот подход предполагает написать архитектуру и логику один раз и не дублировать её при добавлении новых сущностей.
Начнём с краеугольного камня нашей абстракции — абстрактной сущности. Именно с неё начнётся цепочка абстрактных зависимостей, которая послужит каркасом сервиса.
У всех сущностей есть как минимум одно общее поле (обычно больше). Это ID. Вынесем это поле в отдельную абстрактную сущность и унаследуем от неё User и Car.
AbstractEntity:
Не забудьте пометить абстракцию аннотацией @MappedSuperclass — Hibernate тоже должен узнать, что это абстракция.
С Car, соответственно, то же самое.
В каждом слое у нас, помимо бинов, будет один интерфейс с типовыми параметрами и один абстрактный класс с логикой. Кроме репозитория — благодаря специфике Spring Data JPA, здесь всё будет намного проще.
Первое, что нам потребуется в репозитории — общий репозиторий.
CommonRepository:
В этом репозитории мы задаём общие правила для всей цепочки: все сущности, участвующие в ней, будут наследоваться от абстрактной. Далее, для каждой сущности мы должны написать свой репозиторий-интерфейс, в котором обозначим, с какой именно сущностью будет работать эта цепочка репозиторий-сервис-контроллер.
UserRepository:
На этом, благодаря особенностям Spring Data JPA, настройка репозитория заканчивается — всё будет работать и так. Далее следует сервис. Мы должны создать общий интерфейс, абстракцию и бин.
CommonService:
AbstractService:
Здесь мы переопределяем все методы, а также, создаём параметризированный конструктор для будущего репозитория, который мы переопределим в бине. Таким образом, мы уже используем репозиторий, который мы ещё не определили. Мы пока не знаем, какая сущность будет обработана в этой абстракции и какой репозиторий нам потребуется.
UserService:
В бине мы делаем заключительную вещь — явно определяем нужный нам репозиторий, который потом вызовется в конструкторе абстракции. И всё.
При помощи интерфейса и абстракции мы создали магистраль, по которой будем гонять все сущности. В бине же мы подводим к магистрали развязку, по которой будем выводить нужную нам сущность на магистраль.
Контроллер строится по тому же принципу: интерфейс, абстракция, бин.
CommonController:
AbstractController:
UserController:
Это вся структура. Она пишется один раз.
Что дальше?
И вот теперь давайте представим, что у нас появилась новая сущность, которую мы уже унаследовали от AbstractEntity, и нам нужно прописать для неё такую же цепочку. На это у нас уйдёт минута. И никаких копипаст и исправлений.
Возьмём уже унаследованный от AbstractEntity Car.
CarRepository:
CarService:
CarController:
Как мы видим, копирование одинаковой логики состоит в простом добавлении бина. Не надо заново писать логику в каждом бине с изменением параметров и сигнатур. Они написаны один раз и работают в каждом последующем случае.
Заключение
Конечно, в примере описана этакая сферическая ситуация, в которой CRUD для каждой сущности имеет одинаковую логику. Так не бывает — какие-то методы Вам всё равно придётся переопределять в бине или добавлять новые. Но это будет происходить от конкретных потребностей обработки сущности. Хорошо, если процентов 60 от общего количества методов CRUD будет оставаться в абстракции. И это будет хорошим результатом, потому что чем больше мы генерим лишнего кода вручную, тем больше времени мы тратим на монотонную работу и тем выше риск ошибки или опечатки.
Надеюсь, статья была полезна, спасибо за внимание.