Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Queries from method names

The ready-made JpaRepository methods cover work by key. The blog needs more: posts by one author, search by title. Spring Data can build a query from a method name. You declare a method like findByAuthor in the interface, and at startup Spring parses the name and writes the SQL itself.

New repository methods

// 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);
}

The name reads like a phrase: "find by author, order by creation date descending". The second method finds posts whose title contains the text, ignoring case.

What Spring makes of the name

Hibernate prints the resulting 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 '\'

The method argument replaces ?. For Containing Spring wraps the text in % itself.

Service and controller

// 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);
}

Add a couple of posts and check:

curl "http://localhost:8080/api/posts?author=anna"
curl "http://localhost:8080/api/posts/search?q=spring"
[{"id":2,"title":"Spring Data JPA","body":"Repositories","author":"anna","createdAt":"2026-10-04T09:37:51.263464Z"},{"id":1,"title":"Hello, Spring","body":"First post","author":"anna","createdAt":"2026-10-04T09:37:51.134416Z"}]
[{"id":1,"title":"Hello, Spring","body":"First post","author":"anna","createdAt":"2026-10-04T09:37:51.134416Z"},{"id":2,"title":"Spring Data JPA","body":"Repositories","author":"anna","createdAt":"2026-10-04T09:37:51.263464Z"}]

Anna's posts came newest first, and the search for spring found both titles even though they spell Spring with a capital letter.

A name dictionary

Name partExampleSQL
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

You can return a List, an Optional (when you expect at most one result), a long for countBy and a boolean for existsBy.

Common mistake

The name is checked at startup. A typo in a field name stops the application:

No property 'titel' found for type 'Post'

Here the method was called findByTitel. Names in the method must match the entity's fields, not the table's columns: CreatedAt, not created_at. If a name grows longer than a line, it is better to write the query by hand — that is the next lesson.

Thanks for reading!

Donate to the site — we work hard for you.