Spring data jpa что это
Доступ к данным через JPA
Этот урок освещает процесс создания приложения, которое использует Spring Data JPA для сохранения и получения данных из реляционной БД.
Что вы создадите
Вы создадите приложение, которое сохраняет Customer POJO в БД в ОЗУ.
Что вам потребуется
Как проходить этот урок
Как и большинство уроков по Spring, вы можете начать с нуля и выполнять каждый шаг, либо пропустить базовые шаги, которые вам уже знакомы. В любом случае, вы в конечном итоге получите рабочий код.
Чтобы начать с нуля, перейдите в Настройка проекта.
Настройка проекта
Для начала вам необходимо настроить базовый скрипт сборки. Вы можете использовать любую систему сборки, которая вам нравится для сборки проетов Spring, но в этом уроке рассмотрим код для работы с Gradle и Maven. Если вы не знакомы ни с одним из них, ознакомьтесь с соответсвующими уроками Сборка Java-проекта с использованием Gradle или Сборка Java-проекта с использованием Maven.
Создание структуры каталогов
Создание файла сборки Gradle
Ниже представлен начальный файл сборки Gradle. Файл pom.xml находится здесь. Если вы используете Spring Tool Suite (STS), то можете импортировать урок прямо из него.
Spring Boot gradle plugin предоставляет множество удобных возможностей:
Описание простой сущности
В этом примере, вы сохраняете Customer объекты, аннотированные как JPA сущность.
Другие два свойства, firstName и lastName остались не аннотированными. Это значит, что они будут соответствовать колонкам с такими же названиями и параметрами.
Метод tostring будет печатать свойства объекта.
Создание простых запросов
Spring Data JPA ориентирована на использование JPA для сохранения данных в реляционную БД. Наиболее полезной её возможностью является автоматическое создание реализаций репозитория во время выполнения из интерфейса.
Чтобы увидеть, как это работает, создайте интерфейс репозитория, который работает с сущностями Customer :
Приступим к работе и посмотрим, что он найдет!
Создание класса Application
Создайте класс Application со всеми компонентами.
Сборка исполняемого JAR
Вы можете собрать единый исполняемый JAR-файл, который содержит все необходимые зависимости, классы и ресурсы. Это делает его легким в загрузке, версионировании и развертывании сервиса как приложения на протяжении всего периода разработки, на различных средах и так далее.
Затем вы можете запустить JAR-файл:
Если вы используете Gradle, вы можете запустить ваш сервис из командной строки:
Как вариант, вы можете запустить ваш сервис напрямую из Gradle примерно так:
Вы должны увидеть следующее:
Spring Framework и работа с базами данных: Spring Data JPA
В предыдущих постах о работе с базами данных в Spring Framework я поверхностно описал использование JdbcTemplate и NamedParameterJdbcTemplate. Пользоваться данными инструментами безусловно удобно, но у них есть определённые ограничения, среди которых:
В стеке Spring существует проект Spring Data, реализующий большую часть тривиальных задач и упрощающий работу с источниками данных. В качестве источников данных могут использоваться как стандартные реляционные базы данных, так и NoSQL-хранилища вроде MongoDB или Redis.
В мире Java EE стандартом дефакто для работы с базами данных является JPA (Java Persistence API). Spring Data JPA, будучи частью Spring Data, реализует взаимодействие с реляционными СУБД, основываясь на JPA.
Настройка проекта
Для использования Spring Data JPA потребуются следующие зависимости:
Если используется Spring Boot:
Если Spring Boot не используется:
Классы-сущности (Entities)
Классы-сущности дополняются стандартными для JPA аннотациями. В качестве примера возьмём класс Person, использованный уже ранее:
Я добавил в этот класс несколько JPA-аннотаций:
Репозитории
Главными компонентами для взаимодействий с БД в Spring Data являются репозитории. Каждый репозиторий работает со своим классом-сущностью. Самым простым способом создания репозитория является создание интерфейса с наследованием от CrudRepository, как показано в примере:
Первый тип (Person), переданный в дженерик CrudRepository — класс-сущность, с которым должен работать данный репозиторий, второй (String) — тип первичного ключа.
Никаких дополнительных аннотаций для работы данного репозитория не требуется, более того, не требуется даже реализация. При инициализации контекста приложения Spring Data найдёт данный интерфейс и самостоятельно сгенерирует компонент (bean), реализующий данный интерфейс.
Существует несколько типов репозиториев, различающихся по набору возможностей:
И две реализации, которые можно использовать для каких-нибудь нетривиальных задач, вроде написания реализации какого-нибудь метода с нестандартным поведением:
Запросы
Стандартный набор методов для работы с данными, предоставляемый Spring Data, достаточно лаконичен. Мы можем найти все записи класса Person или найти запись по первичному ключу. А что, если нам требуется найти запись Person по email? Данную задачу можно решить несколькими способами.
Аннотация @NamedQuery в классе-сущности
Стандартное для JPA решение — описать именованный запрос в классе-сущности:
Spring Data JPA Tutorial
Управление данными между java-классами или объектами и реляционной базой данных является очень громоздкой и сложной задачей. Уровень DAO обычно содержит много стандартного кода, который следует упростить, чтобы уменьшить количество строк кода и сделать код многократно используемым.
В этом уроке мы обсудим реализацию JPA для весенних данных.
1. Введение
1.1 Что такое JPA?
JPA или Java Persistence API — это спецификация Java для доступа, управления и сохранения данных между классами или объектами Java и реляционной базой данных. Спецификация была введена как часть EJB 3.0.
JPA — это не реализация или продукт, это просто спецификация. Он содержит множество интерфейсов, которые необходимо реализовать. Это структура, которая обеспечивает дополнительный уровень абстракции в реализации JPA. Слой репозитория будет содержать три слоя, как указано ниже.
Spring data JPA позволяет нам не писать никакого стандартного кода, добавляя дополнительный слой хранилища.
1.2 История JPA
JPA2.0: — Разработка JPA2.0 началась в 2007 году как JSR 317. Версия была помечена как 2.0, поскольку она не смогла получить общее согласие для 1.0. Основное внимание было уделено функциям, доступным как часть известных поставщиков ORM.
JPA 2.1: — JPA2.1 был запущен в июле 2011 года как JSR 338. Некоторые из основных функций: граф сущностей, хранимые процедуры, преобразователи и т. Д.
JPA 2.2: — JPA2.2 — последнее дополнение к серии JPA в 2017 году. Оно включает поддержку даты и времени в Java 8, возможность потоковой передачи результатов запроса.
JPA все еще претерпевает много изменений, и мы можем ожидать более новую версию JPA в ближайшее время.
1.3 Spring Data Repositories
Проект Spring Data Commons предоставляет абстракцию хранилища, которая расширяется подпроектами, специфичными для хранилища данных.
Мы должны быть знакомы с интерфейсами репозитория Spring Data, так как это поможет нам в реализации интерфейсов. Давайте посмотрим на интерфейсы.
Spring Data Commons: — В рамках этого проекта предусмотрены следующие интерфейсы:
Spring Data JPA: — Этот проект предоставляет следующие интерфейсы:
Иерархия хранилища выглядит следующим образом:
Иерархия репозитория данных Spring
Давайте попробуем разобраться в Spring Data JPA через пример программы.
1.4 Пользовательский запрос данных Spring
Давайте рассмотрим случай использования, когда мы должны получать данные из базы данных на основе запроса. Написание пользовательского запроса — очень полезный случай. Spring Data JPA имеет разные способы написания пользовательских запросов. Мы будем широко классифицировать пути, как указано ниже.
Преимущество использования этого подхода состоит в том, что он очень прост в реализации. Но ограничение состоит в том, что если запрос содержит более одного параметра, имя метода будет недоступно для чтения. Также ключевые слова, которые не поддерживаются JPA, например, более низкие, не будут полезны при таком подходе.
Преимущество этого подхода в том, что вы можете использовать язык запросов JPA для создания запроса. Кроме того, запрос остается на уровне хранилища. Ограничением этого подхода является то, что @Query может использоваться только тогда, когда поддерживается язык запросов JPA.
Программа, упомянутая ниже, использует оба подхода.
1.5 Spring Data JPA Перевод исключений
Следует учесть, что шаблоны Spring ORM по умолчанию не используются с SPring JPA. Не теряем ли мы трансляцию исключений с помощью Spring Data JPA? Не собираемся ли переводить исключения JPA в иерархию SpringAA DataException?
2. Инструменты и технологии
Давайте посмотрим на технологии и инструменты, используемые для создания программы.
3. Структура проекта
Структура нашего проекта будет выглядеть так, как показано на рисунке ниже.
Структура проекта для учебника JPA по Spring Data
Приведенная выше структура проекта использует Maven. Этот проект также можно создать с помощью Gradle, и файл pom.xml будет заменен файлом build.gradle. Структура проекта будет немного зависеть от использования Gradle для сборки.
4. Цель Программы
В рамках программы мы попытаемся создать простой веб-сервис с использованием весенней загрузки. Этот веб-сервис будет использоваться для манипулирования данными в базе данных PostgreSQL.
Spring Data JPA
В статье опишу использование Spring Data.
Spring Data — дополнительный удобный механизм для взаимодействия с сущностями базы данных, организации их в репозитории, извлечение данных, изменение, в каких то случаях для этого будет достаточно объявить интерфейс и метод в нем, без имплементации.
1. Spring Repository
Основное понятие в Spring Data — это репозиторий. Это несколько интерфейсов которые используют JPA Entity для взаимодействия с ней. Так например интерфейс
public interface CrudRepository extends Repository
обеспечивает основные операции по поиску, сохранения, удалению данных (CRUD операции)
Есть и другие абстракции, например PagingAndSortingRepository.
Т.е. если того перечня что предоставляет интерфейс достаточно для взаимодействия с сущностью, то можно прямо расширить базовый интерфейс для своей сущности, дополнить его своими методами запросов и выполнять операции. Сейчас я покажу коротко те шаги что нужны для самого простого случая (не отвлекаясь пока на конфигурации, ORM, базу данных).
1. Создаем сущность
2. Наследоваться от одного из интерфейсов Spring Data, например от CrudRepository
3. Использовать в клиенте (сервисе) новый интерфейс для операций с данными
Здесь я воспользовался готовым методом findById. Т.е. вот так легко и быстро, без имплементации, получим готовый перечень операций из CrudRepository:
Понятно что этого перечня, скорее всего не хватит для взаимодействия с сущностью, и тут можно расширить свой интерфейс дополнительными методами запросов.
2. Методы запросов из имени метода
Запросы к сущности можно строить прямо из имени метода. Для этого используется механизм префиксов find…By, read…By, query…By, count…By, и get…By, далее от префикса метода начинает разбор остальной части. Вводное предложение может содержать дополнительные выражения, например, Distinct. Далее первый By действует как разделитель, чтобы указать начало фактических критериев. Можно определить условия для свойств сущностей и объединить их с помощью And и Or. Примеры
В документации определен весь перечень, и правила написания метода. В качестве результата могут быть сущность T, Optional, List, Stream. В среде разработки, например в Idea, есть подсказка для написания методов запросов.
Достаточно только определить подобным образом метод, без имплементации и Spring подготовит запрос к сущности.
3. Конфигурация и настройка
Весь проект доступен на github
github DemoSpringData
Здесь лишь коснусь некоторых особенностей.
В context.xml определенны бины transactionManager, dataSource и entityManagerFactory. Важно указать в нем также
путь где определены репозитории.
EntityManagerFactory настроен на работу с Hibernate ORM, а он в свою очередь с БД Oracle XE, тут возможны и другие варианты, в context.xml все это видно. В pom файле есть все зависимости.
4. Специальная обработка параметров
В методах запросов, в их параметрах можно использовать специальные параметры Pageable, Sort, а также ограничения Top и First.
5. Пользовательские реализации для репозитория
Предположим что в репозиторие нужен метод, который не получается описать именем метода, тогда можно реализовать с помощью своего интерфейса и класса его имплементирующего. В примере ниже добавлю в репозиторий метод получения сотрудников с максимальной оплатой труда.
Имплементирую интерфейс. С помощью HQL (SQL) получаю сотрудников с максимальной оплатой, возможны и другие реализации.
А также расширяю Crud Repository Employees еще и CustomizedEmployees.
Здесь есть одна важная особенность. Класс имплементирующий интерфейс, должен заканчиваться (postfix) на Impl, или в конфигурации надо поставить свой postfix
Проверяем работу этого метода через репозиторий
Другой случай, когда надо изменить поведение уже существующего метода в интерфейсе Spring, например delete в CrudRepository, мне надо что бы вместо удаления из БД, выставлялся признак удаления. Техника точно такая же. Ниже пример:
Теперь если в employeesCrudRepository вызвать delete, то объект будет только помечен как удаленный.
6. Пользовательский Базовый Репозиторий
В предыдущем примере я показал как переопределить delete в Crud репозитории сущности, но если это надо делать для всех сущностей проекта, делать для каждой свой интерфейс как то не очень. тогда в Spring data можно настроить свой базовый репозиторий. Для этого:
Объявляется интерфейс и в нем метод для переопределения (или общий для всех сущностей проекта). Тут я еще для всех своих сущностей ввел свой интерфейс BaseEntity (это не обязательно), для удобства вызова общих методов, его методы совпадают с методами сущности.
В конфигурации надо указать этот базовый репозиторий, он будет общий для всех репозиториев проекта
Теперь Employees Repository (и др.) надо расширять от BaseRepository и уже его использовать в клиенте.
Проверяю работу EmployeesBaseRepository
Теперь также как и ранее, объект будет помечен как удаленный, и это будет выполняться для всех сущностей, которые расширяют интерфейс BaseRepository. В примере был применен метод поиска — Query by Example (QBE), я не буду здесь его описывать, из примера видно что он делает, просто и удобно.
7. Методы запросов — Query
Ранее я писал, что если нужен специфичный метод или его реализация, которую нельзя описать через имя метода, то это можно сделать через некоторый Customized интерфейс ( CustomizedEmployees) и сделать реализацию вычисления. А можно пойти другим путем, через указание запроса (HQL или SQL), как вычислить данную функцию.
Для моего примера c getEmployeesMaxSalary, этот вариант реализации даже проще. Я еще усложню его входным параметром salary. Т.е. достаточно объявить в интерфейсе метод и запрос вычисления.
Упомяну лишь еще, что запросы могут быть и модифицирующие, для этого к ним добавляется еще аннотация @Modifying
Так например в моем гипотетическом примере, когда мне надо для всех сущностей иметь признак “удален», я сделаю базовый интерфейс с методом получения списка объектов с признаком «удален» или «активный»
Далее все репозитории для сущностей можно расширять от него. Интерфейсы которые не являются репозиториями, но находятся в «base-package» папке конфигурации, надо аннотировать @NoRepositoryBean.
Теперь когда будет выполняться запрос, в тело запроса будет подставлено имя сущности T для конкретного репозитория который будет расширять ParentEntityRepository, в данном случае Employees.
Spring Data на примере JPA
Введение
Spring Data позволяет легче создавать Spring-управляемые приложения которые используют новые способы доступа к данным, например нереляционные базы данных, map-reduce фреймворки, cloud сервисы, а так же уже хорошо улучшенную поддердку реляционных баз данных.
В этой статье будет рассмотрен один из под-проектов Spring Data — JPA
Что может Spring Data — JPA
Для чего вам может понадобиться Spring Data — JPA
Я бы ответил так — если вам нужно быстро в проекте создать Repository слой базируемый на JPA, предназначенный в основном для CRUD операций, и вы не хотите создавать абстрактные дао, интерфейсы их реализации, то Spring Data — JPA это хороший выбор.
С чего начать
Будем считать у вас уже есть maven проект с подключенным Spring, базой данных, настроенным EntityManager-ом.
1. Добавьте артефакт со Spring Data — JPA
2. В ваш applicationContext.xml нужно добавить путь где будут храниться ваши Repository интерфейсы
3. Создать Entity и Repository интерфейс для него
4. Теперь вы можете использовать созданный интерфейс в вашем приложении
Наследовавшись от CrudRepository вы получили возможность вызывать такие методы как:
без необходимости реализовывать их имплементацию.
Работа с запросами, сортировкой, порционной загрузкой
Рассмотрим на примере: вам нужно сделать запрос, который выберет все Test записи, у которых поле «dummy» установленно в false, и записи отсортированны по полю «tries» в порядке ABC.
Для решения такой задачи вы можете выбрать один из нескольких вариантов:
Если с первым способом все предельно просто и это знакомый запрос, то второй способ заключается в том, чтобы составить имя метода, особым способом использую ключевые слова, такие как: «find», «order», имя переменных и тд. Разработчики Spring Data — JPA постарались учесть большинство возможных вариантов, которые могут вам понадобится.
Specification и CriteriaBuilder
Если вам нужно написать действительно сложный запрос для этого вы можете использовать Specification.
Пример в котором в зависимости от «retries» будут выбраны данные с разными значениями «dummy».
Следующий пример покажет как можно использовать созданный Specification для фильтра всех данных.
Расширим ваш интерфейс при помощи JpaSpecificationExecutor
и вызовем метод findAll передав ему созданную Specification