Что такое query java

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, есть подсказка для написания методов запросов.

Что такое query java. Смотреть фото Что такое query java. Смотреть картинку Что такое query java. Картинка про Что такое query java. Фото Что такое query java
Достаточно только определить подобным образом метод, без имплементации и 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.

Источник

Весенние данные JPA @Query

Узнайте, как использовать аннотацию @Query в Spring Data JPA для определения пользовательских запросов с использованием JPQL и собственного SQL.

1. Обзор

В этом уроке мы продемонстрируем, как использовать аннотацию @Query в Spring Data JPA для выполнения как JPQL, так и собственных SQL-запросов.

Мы также покажем, как построить динамический запрос, когда аннотации @Query недостаточно.

Дальнейшее чтение:

Производные методы запросов в репозиториях Spring Data JPA

Весенние данные JPA @Изменение аннотации

2. Выберите Запрос

Чтобы определить SQL для выполнения для метода хранилища данных Spring, мы можем аннотировать метод с помощью @Query аннотации — его атрибут value содержит JPQL или SQL для выполнения.

Аннотация @Query имеет приоритет над именованными запросами, которые аннотируются с помощью @NamedQuery или определены в orm.xml файл.

Это хороший подход, чтобы поместить определение запроса непосредственно над методом внутри репозитория, а не внутри нашей модели домена в виде именованных запросов. Репозиторий отвечает за сохраняемость, поэтому это лучшее место для хранения этих определений.

2.1. JPQL

По умолчанию в определении запроса используется JPQL.

Давайте рассмотрим простой метод репозитория, который возвращает активные User сущности из базы данных:

2.2. Родной язык

Мы также можем использовать собственный SQL для определения нашего запроса. Все, что нам нужно сделать, это установить значение атрибута NativeQuery в true и определить собственный SQL-запрос в атрибуте value аннотации:

3. Определите порядок в запросе

3.1. Сортировка по предоставленным JPA и производным методам

Для методов, которые мы получаем из коробки, таких как findAll(Sort) или те, которые генерируются путем анализа сигнатур методов, мы можем использовать только свойства объекта для определения нашей сортировки :

Теперь представьте, что мы хотим отсортировать по длине свойства name:

Когда мы выполним приведенный выше код, мы получим исключение:

org.springframework.data.mapping.Исключение PropertyReferenceException: Для типа User не найдена ДЛИНА свойства(имя)!

3.2. JPQL

Когда мы используем JPQL для определения запроса, то данные Spring могут обрабатывать сортировку без каких — либо проблем – все, что нам нужно сделать, это добавить параметр метода типа Sort :

Очень важно, чтобы мы использовали JpaSort.небезопасно() чтобы создать Сортировать экземпляр объекта.

Когда мы используем:

3.3. Родной язык

Если мы это сделаем, мы получим исключение:

org.springframework.data.jpa.repository.запрос.Недопустимое исключение JpaQueryMethod: Невозможно использовать собственные запросы с динамической сортировкой и/или разбиением на страницы

Как говорится в исключении, сортировка не поддерживается для собственных запросов. Сообщение об ошибке дает нам намек на то, что разбиение на страницы также вызовет исключение.

Тем не менее, есть обходной путь, который позволяет разбиение на страницы, и мы рассмотрим его в следующем разделе.

4. Разбиение на страницы

Еще одним преимуществом разбиения на страницы является то, что объем данных, отправляемых с сервера на клиент, сводится к минимуму. Отправляя меньшие фрагменты данных, мы, как правило, видим улучшение производительности.

4.1. JPQL

Использование разбиения на страницы в определении запроса JPQL является простым:

Мы можем пройти PageRequest параметр для получения страницы данных.

Разбиение на страницы также поддерживается для собственных запросов, но требует небольшой дополнительной работы.

4.2. Родной язык

Мы можем включить разбиение на страницы для собственных запросов, объявив дополнительный атрибут countQuery .

Это определяет SQL, который нужно выполнить, чтобы подсчитать количество строк во всем результате:

4.3. Версии Spring Data JPA до версии 2.0.4

Приведенное выше решение для собственных запросов отлично работает для Spring Data JPA версий 2.0.4 и более поздних.

До этой версии, когда мы попытаемся выполнить такой запрос, мы получим то же исключение, которое мы описали в предыдущем разделе о сортировке.

Мы можем преодолеть это, добавив дополнительный параметр для разбиения на страницы внутри нашего запроса:

Мы рассмотрели, как создавать простые запросы select с помощью JPQL и собственного SQL. Далее мы покажем, как определить дополнительные параметры.

5. Параметры индексированного запроса

Существует два возможных способа передачи параметров метода в наш запрос: индексированные и именованные параметры.

В этом разделе мы рассмотрим индексированные параметры.

5.1. JPQL

Для индексированных параметров в JPQL данные Spring будут передавать параметры метода в запрос в том же порядке, в котором они отображаются в объявлении метода :

5.2. Родной язык

Индексированные параметры для собственных запросов работают точно так же, как и для JPQL:

В следующем разделе мы покажем другой подход: передача параметров через имя.

6. Именованные параметры

Мы также можем передать параметры метода в запрос, используя именованные параметры. Мы определяем их с помощью аннотации @Param внутри объявления метода репозитория.

6.1. JPQL

Как упоминалось выше, мы используем аннотацию @Param в объявлении метода для сопоставления параметров, определенных по имени в JPQL, с параметрами из объявления метода:

Обратите внимание, что в приведенном выше примере мы определили, что наши параметры SQL-запроса и метода имеют одинаковые имена, но это не обязательно, если строки значений совпадают:

6.2. Родной язык

Для определения собственного запроса нет никакой разницы в том, как мы передаем параметр через имя в запрос по сравнению с JPQL — мы используем аннотацию @Param :

7. Параметр Сбора

Давайте рассмотрим случай, когда предложение where нашего запроса JPQL или SQL содержит ключевое слово IN (или NOT IN ):

В этом случае мы можем определить метод запроса, который принимает Collection в качестве параметра:

8. Обновите Запросы С Помощью @Modifying

Мы можем использовать аннотацию @ Query для изменения состояния базы данных, также добавив метод @ Modifying annotation в репозиторий.

8.1. JPQL

Метод репозитория, который изменяет данные, имеет два отличия по сравнению с запросом select — он имеет аннотацию @Modifying и, конечно, запрос JPQL использует update вместо select :

Возвращаемое значение определяет, сколько строк было обновлено при выполнении запроса. В запросах обновления можно использовать как индексированные, так и именованные параметры.

8.2. Родной язык

Мы также можем изменить состояние базы данных с помощью собственного запроса. Нам просто нужно добавить аннотацию @Modifying :

8.3. Вставки

9. Динамический запрос

Часто мы сталкиваемся с необходимостью построения операторов SQL на основе условий или наборов данных, значения которых известны только во время выполнения. И в этих случаях мы не можем просто использовать статический запрос.

9.1. Пример динамического запроса

Поскольку набор строится динамически, мы не можем знать во время компиляции, сколько предложений LIKE нужно добавить.

В этом случае мы не можем просто использовать аннотацию @Query , так как мы не можем предоставить статическую инструкцию SQL.

Вместо этого, реализуя пользовательский составной репозиторий, мы можем расширить базовую функциональность JpaRepository и предоставить нашу собственную логику для построения динамического запроса. Давайте посмотрим, как это сделать.

9.2. Пользовательские репозитории и API критериев JPA

Мы начнем с создания пользовательского интерфейса фрагмента:

И тогда мы его реализуем:

Как показано выше, мы использовали API критериев JPA чтобы построить наш динамический запрос.

9.3. Расширение существующего репозитория

Итак, теперь мы интегрируем наш фрагмент, расширив новый интерфейс в UserRepository :

9.4. Использование Репозитория

И, наконец, мы можем вызвать наш метод динамического запроса:

Мы успешно создали составной репозиторий и вызвали наш пользовательский метод.

10. Заключение

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

Источник

QUERY

Query – основной класс, для работы с БД, через него происходит выборка, запись, обновление и удаление данных. Также можно проводить определенную обработку данных, полученных из БД. Экземпляр класса получаем через фабрику (смотри раздел УСТАНОВКА).

Описание функций

Все функции класса условно можно разбить на 4 группы. Для удобства присвоим каждой группе свой цвет:

Функции all() и aggregator()

Проще всего рассмотреть принцип работы функций на основе примера. В качестве примера возьмём вот такую схему базы данных:

Что такое query java. Смотреть фото Что такое query java. Смотреть картинку Что такое query java. Картинка про Что такое query java. Фото Что такое query java

mark (m)
idstudent idlesson idmark
1113
2114
3122
4122
5123
6145
7212
8213
9225
10244
11233
12232
13225
14233
15212
16342
17315
18322
19343
20334
coursework (c)
idstudent idtitlesemester number
11Архитектура и производительность серверных ЦП1
22Закон единства и борьбы противоположностей1
32Серверные платформы RISC/UNIX2
42Вредоносное программное обеспечение3
52Графическое программирование на Ms Fortran4
63«Азы» программирования и обучающие программы1
73История возникновения Интернета2
student (s)
idnamesemester number
1Даша1
2Маша4
3Паша2
lesson (l)
idname
1КоМод
2Матан
3Физ-ра
4Философия

Зачастую при запросе к БД хочется получить не плоский ответ, а древовидный. К примеру, выполнив такой запрос:

Получим плоский результат:

Здесь данные из таблицы student дублируются, а мы бы хотели увидеть такой результат:

Чтобы добиться такого результата, необходимо в функцию all передать массив с опциями:

Рассмотрим более сложный пример. Допустим нам надо получить всех студентов с названием их курсовых и со всеми оценками по всем предметам. Мы бы хотели получить это не в плоском виде, а в древовидном, без дублей. Ниже приведен нужный запрос к БД и результат.

student idstudent namesemester numbercoursework idcoursework semestercoursework titlelesson idlessonmark idmark
с таблицы: studentс таблицы: courseworkс таблицы: lessonс таблицы: mark
1Даша111Архитектура и производительность серверных ЦП1КоМод13
1Даша111Архитектура и производительность серверных ЦП1КоМод24
1Даша111Архитектура и производительность серверных ЦП2Матан32
1Даша111Архитектура и производительность серверных ЦП2Матан42
1Даша111Архитектура и производительность серверных ЦП2Матан53
1Даша111Архитектура и производительность серверных ЦП4Философия65
2Маша421Закон единства и борьбы противоположностей1КоМод72
2Маша421Закон единства и борьбы противоположностей1КоМод83
2Маша421Закон единства и борьбы противоположностей1КоМод152
2Маша421Закон единства и борьбы противоположностей2Матан95
2Маша421Закон единства и борьбы противоположностей2Матан135
2Маша421Закон единства и борьбы противоположностей3Физ-ра113
2Маша421Закон единства и борьбы противоположностей3Физ-ра122
2Маша421Закон единства и борьбы противоположностей3Физ-ра143
2Маша421Закон единства и борьбы противоположностей4Философия104
2Маша432Серверные платформы RISC/UNIX1КоМод72
2Маша432Серверные платформы RISC/UNIX1КоМод83
2Маша432Серверные платформы RISC/UNIX1КоМод152
2Маша432Серверные платформы RISC/UNIX2Матан95
2Маша432Серверные платформы RISC/UNIX2Матан135
2Маша432Серверные платформы RISC/UNIX3Физ-ра113
2Маша432Серверные платформы RISC/UNIX3Физ-ра122
2Маша432Серверные платформы RISC/UNIX3Физ-ра143
2Маша432Серверные платформы RISC/UNIX4Философия104
2Маша443Вредоносное программное обеспечение1КоМод72
2Маша443Вредоносное программное обеспечение1КоМод83
2Маша443Вредоносное программное обеспечение1КоМод152
2Маша443Вредоносное программное обеспечение2Матан95
2Маша443Вредоносное программное обеспечение2Матан135
2Маша443Вредоносное программное обеспечение3Физ-ра113
2Маша443Вредоносное программное обеспечение3Физ-ра122
2Маша443Вредоносное программное обеспечение3Физ-ра143
2Маша443Вредоносное программное обеспечение4Философия104
2Маша454Графическое программирование на Ms Fortran1КоМод72
2Маша454Графическое программирование на Ms Fortran1КоМод83
2Маша454Графическое программирование на Ms Fortran1КоМод152
2Маша454Графическое программирование на Ms Fortran2Матан95
2Маша454Графическое программирование на Ms Fortran2Матан135
2Маша454Графическое программирование на Ms Fortran3Физ-ра113
2Маша454Графическое программирование на Ms Fortran3Физ-ра122
2Маша454Графическое программирование на Ms Fortran3Физ-ра143
2Маша454Графическое программирование на Ms Fortran4Философия104
3Паша261«Азы» программирования и обучающие программы1КоМод175
3Паша261«Азы» программирования и обучающие программы2Матан182
3Паша261«Азы» программирования и обучающие программы3Физ-ра204
3Паша261«Азы» программирования и обучающие программы4Философия162
3Паша261«Азы» программирования и обучающие программы4Философия193
3Паша272История возникновения Интернета1КоМод175
3Паша272История возникновения Интернета2Матан182
3Паша272История возникновения Интернета3Физ-ра204
3Паша272История возникновения Интернета4Философия162
3Паша272История возникновения Интернета4Философия193

Пагинация с агрегированным запросом считает только верхние, самые основные данные. В приведенном выше примере для пагинации будет только 3 строчки.

whereWithJoin()

$options рассмотрим на примере:

Внутри одной скобки псевдонимы будут одинаковые (использована одна таблица). Ниже в примерах это видно.

Бывает необходимо написать запрос в рамках одной таблицы с поиском по нескольким столбцам, причем условие по нескольким столбцам описывает одну сущность (со связью И), а нам нужно поискать несколько сущностей. К примеру в таблице t есть две колонки cl1 и cl2. Составим запрос на псевдокоде:

Данный запрос вернет нам пустую выборку, для корректной работы необходимо таблицу t сджойнить, это уже будет таблица t ‘, тогда правильный запрос будет:

На практике это может понадобиться при поиске по динамическим свойствам динамических объектов. Давайте рассмотрим этот вариант на примере.

Сделаем упрощенный, демонстрационный вариант. У нас есть таблица product, куда записываются новые, поступающие товары. У нее будет 2 колонки: тип товара и id. Так же будет табличка properties, где будут хранится все свойства товаров. В табличке val будут хранится id товара, id свойств этого товара и значения этих свойств. Вот содержимое таблиц:

Что такое query java. Смотреть фото Что такое query java. Смотреть картинку Что такое query java. Картинка про Что такое query java. Фото Что такое query java

К примеру пользователь на фронтенде сформировал следующее условие:

«Получить все товары у которых лошадиных сил меньше 100 или диагональ экрана меньше 6 дюймов. Также товары должны весить меньше тонны и быть в эксплуатации больше месяца.»

Как видим из результата запроса, мы получили 18 записей, хотя по сути тут всего 2 товара, давайте приведем результат к древовидному виду и избавимся от дублей с помощью функции aggregator() или выполнив запрос с массивом настроек агрегации:

Примеры

Пример 1

Необходимо получить список студентов и количество каждой из оценок (сколько 2, 3, 4 и 5) по всем предметам. Также нужно использовать постраничное разбиение, показать результаты первой страницы (по 2 записи на странице).

В sorts название столбцов пишутся без префиксов.

Для студентки Даши получить средний бал по всем предметам.

Пример 2

Пользователь должен иметь возможность получить всех студентов, которые подходят под указанные им критерии, а именно пользователь указывает оценки и массив id предметов, у которых должна встречаться такая оценка.

В результате будет сгенерирован примерно следующий sql запрос:

Источник

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *