Это сообщение № 3 из серии “Запрос вашего хранилища Spring Data JPA”.
Если вы следите за сериалом, то к настоящему времени у вас уже есть приложение со списком ресторанов. Список извлекается с помощью метода find All()
который вы не реализовали, потому что он был предоставлен Spring Data JPA, когда вы создали класс RestaurantRepository
, расширяющий класс Spring JpaRepository
.
Взгляните на предыдущий пост, если вы еще этого не сделали:
Запрос к вашему репозиторию Spring Data JPA – Базовая настройка
Бруно Друговик ・ 12 января ・ 4 мин читать
Допустим, теперь вам нужно добавить строку поиска поверх списка, чтобы отфильтровать его. Поиск должен соответствовать любому названию ресторана, содержащему текст, который вводит пользователь.
Как вы можете видеть, если пользователь вводит Ma
показаны три ресторана: Mamma Mia
; La Maison du Croissant
; и Marcante Pizzaria
. Все они содержат Много
в их названиях.
Что ж, давайте подготовим наше приложение к работе с этим новым требованием.
Панель поиска
Давайте добавим строку поиска со следующим кодом Thymeleaf на index.html
файл:
Это простая форма, которая попадает на /поиск
адрес с двумя параметрами запроса:
поле
, содержащее имя поля, по которому пользователь хочет выполнить поиск (пока поддерживается толькоname
).запрос
содержащий все, что пользователь вводит в поле поиска.
URL-адрес после нажатия кнопки поиска с помощью Ma
в поле поиска будет https://whatever-your-server-is/search ?поле= имя и запрос=Ma
.
Способ управления
Нам нужен метод на IndexPage.java
контроллер для обработки поиска пользователя. Это метод, который делает свое дело:
@RequestMapping("/search") public String indexWithQuery(@RequestParam("query") String query, @RequestParam("field") String field, Model model) { if (field.equals("name")) { // TODO add search by name here. } model.addAttribute("field", field); model.addAttribute("query", query); return "index"; }
Давайте разберемся, что здесь важно:
@RequestMapping("/поиск")
привязывает этот метод к запросу, который будет выполнять форма, которую мы добавили ранее.@RequestParam("запрос") Строковый запрос
и@RequestParam("поле") Строковое поле
привязать параметры запроса (переменные после?
по URL-адресу) к переменным Java, которые мы можем использовать.
Остальная часть кода:
- выполняет поиск (еще не реализован);
- возвращает параметры, выбранные/введенные пользователем в форме поиска (представляется разумным отображать эту информацию в отфильтрованном списке ресторанов);
- и перенаправляет пользователя на страницу индекса с новой информацией, которую мы только что (пока нет:)
Что ж, похоже, теперь нам предстоит проделать тяжелую работу, а именно найти все рестораны, в названиях которых есть определенная строка.
Мы делаем это с помощью этого огромного и сложного кода на RestaurantRepository.java
интерфейс:
ListfindAllByNameContaining(String query);
И теперь, заменив это , ЧТОБЫ СДЕЛАТЬ
мы добавили ранее на IndexPage.java
контроллер со следующим:
model.addAttribute("restaurants", restaurantRepository.findAllByNameContaining(query));
… ваш новый поиск работает! Хочешь попробовать?
На самом деле это довольно просто: Spring Data анализирует имя метода на основе определенных критериев и создает для вас запрос. Вот как это происходит в этом примере ( findAllByName, содержащий(имя строки)
):
find
определяет, что объекты должны быть возвращены. Также может бытьчтение
,запрос
иполучите
с тем же эффектом. Если бы это былcount
, он вернул бы количество объектов.Все
игнорируется. Обратите внимание, что здесь могут быть использованы некоторые ключевые слова.С помощью
указывает анализатору начало фактического критерия.Name
сообщает Spring Data, что в базовом объекте этого репозитория (Restaurant
) есть свойство с именемname
, которое будет использоваться в качестве критерия поиска. Другими словами, в этом свойстве будет предложениеwhere
.Содержащий
задает оператор для предложенияwhere
. Если не указано, подразумевается=
.(Имя строки)
указывает параметр, который будет получен во время выполнения для использования в качестве значения в предложенииwhere
.
Я объяснил, но это довольно самоочевидно, тебе не кажется? Что ж, имея это в виду, давайте подумаем о некоторых других допустимых методах, следующих той же структуре:
найти Все По Названию Кухни, Содержащему (Строка кухня)
возвращает рестораны, кухня которых содержит указанное значение/строку. Обратите внимание, что мы запрашиваем рестораны, но используем поля из объекта Cuisine, потому что данные Spring пересекают вложенные свойства!Findallbydeliveryfeislessthanequal(бесплатная доставка в десятичных числах)
возвращает рестораны, стоимость доставки которых меньше или равна предоставленнойстоимость доставки
стоимость. Обратите внимание, что тип параметра соответствует типу свойства объекта.
Теперь у вас есть больше возможностей для поиска:
Другие допустимые методы:
подсчитайте по названию кухни(строка cuisine)
, чтобы вернуть количество ресторанов с заданным типом кухни.найдите Топ По названию кухни, Закажите По стоимости доставки Asc(String cuisine)
, чтобы вернуть ресторан с самой дешевой платой за доставку данной кухни.
И их использование:
Репозиторий со всеми запросами даже не является конкретным классом, в вашем коде нет реализации:
public interface RestaurantRepository extends JpaRepository{ List findAllByNameContaining(String query); List findAllByCuisineNameContaining(String cuisine); List findAllByDeliveryFeeIsLessThanEqual(BigDecimal deliveryFee); long countByCuisineName(String cuisine); Restaurant findTopByCuisineNameOrderByDeliveryFeeAsc(String cuisine); }
Вы можете найти более подробную информацию, включая список поддерживаемых ключевых слов, в официальной документации .
Рабочее приложение находится здесь (подождите, пока Heroku загрузит приложение, на бесплатном уровне это займет несколько секунд).
Добавляет строку поиска: d5a02bb Добавляет параметры поиска и страницу поиска: dd6793b commit.
brunodrugowick/jpa-запросы-сообщение в блоге
Демонстрационный проект для сообщения в блоге о JPA (Spring Data).
Оригинал: “https://dev.to/brunodrugowick/spring-data-jpa-query-methods-l43”