BackendBench
Coffee

Unravel › Java concepts › Persistence and JPA

Persistence

Spring Data repositories

A Spring Data repository is an interface only.

Learn these first

At a glance

Mental model

You describe the questions you want to ask the filing cabinet ("find by email") and Spring builds the clerk who answers them.

What happens, in order
  1. 1Declare interface OrderRepository extends JpaRepository<Order, Long> and inject itYou immediately get save, findById, findAll, deleteById, paging and sorting.
  2. 2Method names are parsed: findByStatusAndCreatedAfter(status, date) becomes a query on those fields@Query supplies JPQL or SQL when a name would get unwieldy.
  3. 3Pageable and Page give database-level paging (limit and offset) instead of loading everything and slicing in memory
Remember
Watch out
Returning huge lists without pagingCalling save in a loop of thousands of rows (one statement each)Stale entities after a @Modifying query
Example (highlighted lines explain it)
public interface OrderRepository extends JpaRepository<Order, Long> {    List<Order> findByStatusAndCreatedAtAfter(String status, Instant since);    @Query("select o from Order o where o.customer.id = :customerId")    Page<Order> forCustomer(long customerId, Pageable pageable);}
  1. line 1 uses JpaRepository, the core of Spring Data repositories
  2. line 4 uses Query, the core of Spring Data repositories
  3. line 5 uses Page, the core of Spring Data repositories
Read the full explanation (about 1 min)

A Spring Data repository is an interface only. Spring writes the implementation: methods like findByEmail become queries, and save, findById and delete come built in.

A mental model

You describe the questions you want to ask the filing cabinet ("find by email") and Spring builds the clerk who answers them.

How it works

Declare interface OrderRepository extends JpaRepository<Order, Long> and inject it. You immediately get save, findById, findAll, deleteById, paging and sorting.

Method names are parsed: findByStatusAndCreatedAfter(status, date) becomes a query on those fields. @Query supplies JPQL or SQL when a name would get unwieldy.

Pageable and Page give database-level paging (limit and offset) instead of loading everything and slicing in memory.

Going deeper

A method that returns a List for a table with a million rows loads all of them into memory. Use paging or streaming.

@Modifying queries run an UPDATE or DELETE directly and bypass the persistence context, so entities already loaded in the same transaction may be stale.

Derived queries with many conditions become unreadable names. When the name exceeds a sentence, write a @Query.

Under the hood

At startup Spring creates a JDK proxy for each repository interface, backed by SimpleJpaRepository. Query methods are parsed once into PartTree objects and turned into JPA criteria queries.

Common mistakes

  • Returning huge lists without paging.
  • Calling save in a loop of thousands of rows (one statement each).
  • Stale entities after a @Modifying query.

How Unravel recognises it

When you paste code, Unravel looks for these signs of spring data repositories. Spotting them yourself is a good habit when you read unfamiliar code:

Part of a learning path

Related concepts

Builds on this

Frequently asked questions

What is Spring Data repositories?

A Spring Data repository is an interface only. Spring writes the implementation: methods like findByEmail become queries, and save, findById and delete come built in.

What are the most common mistakes with Spring Data repositories?

Returning huge lists without paging. Calling save in a loop of thousands of rows (one statement each). Stale entities after a @Modifying query.

How can I see Spring Data repositories in real code?

Paste your own Java into Unravel and it will point out where spring data repositories appears, explain how it works at the detail level you choose, and draw the flow of the code around it.