Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Запросы по имени метода

Готовых методов JpaRepository хватает для работы по ключу. Но блогу нужно больше: статьи одного автора, поиск по заголовку. Spring Data умеет строить запрос по имени метода. Вы объявляете в интерфейсе метод вроде findByAuthor, а Spring при запуске разбирает название и пишет SQL сам.

Новые методы репозитория

// src/main/java/com/example/blog/PostRepository.java
package com.example.blog;
 
import java.util.List;
 
import org.springframework.data.jpa.repository.JpaRepository;
 
public interface PostRepository extends JpaRepository<Post, Long> {
 
    List<Post> findByAuthorOrderByCreatedAtDesc(String author);
 
    List<Post> findByTitleContainingIgnoreCase(String text);
}

Имя читается как фраза: «найти по автору, упорядочить по дате создания по убыванию». Второй метод ищет статьи, в заголовке которых есть текст, без учёта регистра.

Что Spring сделает из имени

Hibernate печатает получившийся SQL:

Hibernate: select p1_0.id,p1_0.author,p1_0.body,p1_0.created_at,p1_0.title from posts p1_0 where p1_0.author=? order by p1_0.created_at desc
Hibernate: select p1_0.id,p1_0.author,p1_0.body,p1_0.created_at,p1_0.title from posts p1_0 where upper(p1_0.title) like upper(?) escape '\'

Вместо ? подставляется аргумент метода. Для Containing Spring сам обернёт текст знаками %.

Сервис и контроллер

// src/main/java/com/example/blog/PostService.java
public List<PostResponse> findAll(String author) {
    List<Post> found = author == null
            ? posts.findAll()
            : posts.findByAuthorOrderByCreatedAtDesc(author);
    return found.stream().map(PostResponse::from).toList();
}
 
public List<PostResponse> search(String text) {
    return posts.findByTitleContainingIgnoreCase(text).stream()
            .map(PostResponse::from)
            .toList();
}
// src/main/java/com/example/blog/PostController.java
@GetMapping
public List<PostResponse> list(@RequestParam(required = false) String author) {
    return postService.findAll(author);
}
 
@GetMapping("/search")
public List<PostResponse> search(@RequestParam String q) {
    return postService.search(q);
}

Добавьте пару статей и проверьте:

curl "http://localhost:8080/api/posts?author=anna"
curl "http://localhost:8080/api/posts/search?q=spring"
[{"id":2,"title":"Spring Data JPA","body":"Репозитории","author":"anna","createdAt":"2026-10-04T09:37:51.263464Z"},{"id":1,"title":"Привет, Spring","body":"Первая статья","author":"anna","createdAt":"2026-10-04T09:37:51.134416Z"}]
[{"id":1,"title":"Привет, Spring","body":"Первая статья","author":"anna","createdAt":"2026-10-04T09:37:51.134416Z"},{"id":2,"title":"Spring Data JPA","body":"Репозитории","author":"anna","createdAt":"2026-10-04T09:37:51.263464Z"}]

Статьи Анны пришли от новой к старой, а поиск по spring нашёл оба заголовка, хотя в них Spring с большой буквы.

Словарь имён

Часть имениПримерSQL
findBy, countBy, existsBy, deleteBycountByAuthorselect, count, exists, delete
And, OrfindByAuthorAndTitleand, or
Containing, StartingWithfindByTitleStartingWithlike
IgnoreCasefindByTitleIgnoreCaseupper(...)
After, Before, BetweenfindByCreatedAtAfter>, <, between
GreaterThan, LessThanfindByIdGreaterThan>, <
InfindByAuthorIn(List<String>)in (...)
OrderBy...Asc, DescfindByAuthorOrderByTitleAscorder by
First, Top10findTop10ByOrderByCreatedAtDesclimit

Возвращать можно List, Optional (если ждёте не больше одного результата), long для countBy и boolean для existsBy.

Частая ошибка

Имя проверяется при запуске. Опечатка в названии поля остановит приложение:

No property 'titel' found for type 'Post'

Здесь метод назывался findByTitel. Имена в методе должны совпадать с полями сущности, а не со столбцами таблицы: CreatedAt, а не created_at. Если имя получается длиннее строки, лучше написать запрос вручную — об этом следующий урок.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.