Запросы по имени метода
Готовых методов 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, deleteBy | countByAuthor | select, count, exists, delete |
And, Or | findByAuthorAndTitle | and, or |
Containing, StartingWith | findByTitleStartingWith | like |
IgnoreCase | findByTitleIgnoreCase | upper(...) |
After, Before, Between | findByCreatedAtAfter | >, <, between |
GreaterThan, LessThan | findByIdGreaterThan | >, < |
In | findByAuthorIn(List<String>) | in (...) |
OrderBy...Asc, Desc | findByAuthorOrderByTitleAsc | order by |
First, Top10 | findTop10ByOrderByCreatedAtDesc | limit |
Возвращать можно List, Optional (если ждёте не больше одного результата), long для countBy и boolean для existsBy.
Частая ошибка
Имя проверяется при запуске. Опечатка в названии поля остановит приложение:
No property 'titel' found for type 'Post'Здесь метод назывался findByTitel. Имена в методе должны совпадать с полями сущности, а не со столбцами таблицы: CreatedAt, а не created_at. Если имя получается длиннее строки, лучше написать запрос вручную — об этом следующий урок.