Repository со Spring Data

  • Рубрика записи:Spring back-end

SQL-запросы для операций с данными в большинстве своём однообразны. А что умные программисты делают с однообразными операциями? Правильно, автоматизируют!

В мире Spring, репозиторий (repository) – это специальный компонент, отвечающий за взаимодействие с базой данных. Он предоставляет методы для выполнения операций типа CRUD (Create, Read, Update, Delete). Давайте разберёмся, как создать репозитории для сущностей.

Создание интерфейса Repository

После создания классов-сущностей встаёт вопрос: а что нам с ними делать? Откуда их загружать, куда их сохранять? На эти вопросы даёт ответ слой repository – один из слоёв структуры Spring-проекта.

В общем-то, вот как взаимодействуют между собой БД, репозитории, сервисы и контроллеры:

Схема цепочки действий в Spring-проекте с БД, репозиторием, сервисом и контроллером

В Spring для создания репозитория используется интерфейс. Не класс. Вы, наверное, подумаете – интерфейс, значит, его придётся где-то реализовывать. Но нет! Это невероятно, но вы просто напишете интерфейс, а Spring его реализует самостоятельно. Да, Spring Data JPA (Java Persistence API) возьмёт на себя эту задачу и автоматически предоставит реализацию во время выполнения.

Для того, чтобы создать репозиторий, нужно унаследовать интерфейс от одного из интерфейсов-шаблонов репозиториев. В Spring есть два основных интерфейса для репозиториев: CrudRepository и JpaRepository. Основное отличие в том, что JpaRepository предоставляет дополнительные методы для работы с JPA. В общем, можете просто не заморачиваться с этим и использовать JpaRepository:

В треугольных скобках после JpaRepository нужно указать 2 типа. Первый – это тип сущности (т.е. класс пользователя, User). Второй – тип идентификатора. Так как у класса User поле id имеет тип данных Long, то указываем здесь Long.

Что дальше? Так и всё. Хе-хе. Нет, правда. Да, даже методы можно не писать. И уж точно не реализовывать интерфейс. Думаете, он слишком пустой? Ну, давайте проверим.

Подсказки методов для объекта репозитория UserRepository в рамках проекта Spring

Создадим в другом месте в коде переменную типа UserRepository. И поставим точку – чтобы среда разработки IntelliJ IDEA заботливо предоставила список подсказок, что можно вызвать у объекта UserRepository. Вы тоже это видите?

Ага, именно так. Весь этот огромный список – это автоматически сгенерированные методы для оперирования с сущностью User. И это всё уже готово. Причём видно, что некоторые методы сразу сделаны именно под класс сущности User. Например, метод findAll() возвращает List<User>. Можно удалить пользователя по id методом deleteByID(Long id). А можно найти его по id методом findById(Long id). Можно сохранить или проверить на существование. Но это ещё не всё. Это не все возможности, которые предоставляет Spring Data и JpaRepository в частности.

Что примечательно, так это то, что метод save() у репозитория может работать двумя способами: на INSERT и на UPDATE. Создание новой строки в таблице он производит, если идентификатор (id) объекта сущности пуст (равен null). А если нет – тогда он проводит обновление уже имеющейся сущности с имеющимся id.

Давайте узнаем, как создавать свои методы в репозитории.

Собственные методы

Итак, хотя JpaRepository воистину творит магию даже при пустом интерфейсе, его может не хватить для задач вашего проекта. Но этот интерфейс легко дополнить. Дело в том, что даже добавление новых методов не потребует их реализации. Spring Data JPA предоставляет механизм создания собственных методов в репозитории на основе соглашений именования. Эти методы автоматически преобразуются в соответствующие запросы базы данных.

То есть если вы хотите осуществить поиск по каким-либо критериям, вы начинаете метод со слов “findBy“. И дальше среда разработки вам подскажет варианты в зависимости от полей, имеющихся в сущности:

Так как у класса User есть несколько полей (id, email, password, username, posts), то по ним репозиторий и предлагает искать. С этими полями, как видно в подсказках IDE, можно делать практически всё что угодно. Например, с email среда разработки предлагает и простой поиск совпадения, и email-ы, содержащие подстроку, и пустые email-ы, и email-ы, которые заканчиваются подстрокой… В общем, полёт фантазии. Вы можете выбирать, что вам нужно для вашей задачи. Но чаще всего дело ограничивается простым поиском по полю.

Подсказки новых методов, начинающихся с findBy, для объекта репозитория UserRepository в рамках проекта Spring

Например, метод поиска по email-у будет выглядеть так:

Кстати, здесь уже не список пользователей, List<User>, а просто User, так как мы уверены, что у каждого пользователя будет уникальный email. Как и раньше – метод реализовывать не нужно. Он будет сделан автоматически. SQL-запросы тоже. Ну красота, не правда ли?

Можно комбинировать несколько условий. Это делается при помощи слова And (если нужно одновременное совпадение). Также можно с помощью слова Or помечать, что должно выполняться одно из условий.

Вот ещё парочка примеров методов:

Запросы с @Query

Соглашения именования в Spring Data JPA позволяют создавать множество методов без необходимости написания явных запросов SQL. Однако в случае более сложных запросов всегда есть возможность использовать аннотацию @Query для написания своих SQL-запросов.

Например, поиск по возрасту:

Здесь u – это алиас (псевдоним) таблицы пользователей: u представляет объект пользователя (User), который является экземпляром класса, а не непосредственно таблицей в базе данных. Таким образом, запрос ассоциируется с объектами сущности User.

Если вы хотите написать привычный SQL-запрос без вот этих вот алиасов, нужно установить параметр nativeQuery в true:

В основном @Query используется для сложных запросов, но используется редко. Для запросов, по сложности сопоставимых с такими:

Пример с users и posts

Вот мы и подошли к созданию репозиториев для нашего примера: для созданных ранее в БД таблиц users и posts, которым соответствуют сущности User и Post.

Для пользователя User практически достаточно методов из JpaRepository. Введём лишь один дополнительный метод, позволяющий искать по email-у:

Для записи Post также почти нет необходимости вводить новые методы. Только один – получение постов от конкретного пользователя.

Вот так и происходит работа с БД средствами Spring Data. По-моему, это прикольно и удобно. Далее репозитории будут использоваться сервисами, которые являются оплотом бизнес-логики Spring-приложения.

Добавить комментарий