What is JpaRepository and where does it sit in the Spring Data repository interface hierarchy?
answer
- Repository -> CrudRepository -> ListCrudRepository
- PagingAndSorting split from Crud in 3.0
- JpaRepository adds flush/batch/getReferenceById
- SimpleJpaRepository is the backing impl
- extend for convenience, narrow to restrict
basics
~10 sJpaRepository is the JPA-specific top interface you extend to get ready-made CRUD, paging and sorting methods for an entity, without writing any implementation — Spring generates one at runtime.
solid answer
~40 sJpaRepository<T,ID> is the JPA-specialised repository at the top of the Spring Data hierarchy. It inherits from ListCrudRepository (save, findById, findAll returning List, delete, count, existsById) and ListPagingAndSortingRepository (findAll(Pageable), findAll(Sort)), plus QueryByExampleExecutor. On top it adds JPA-only methods: flush(), saveAndFlush(), saveAllAndFlush(), deleteAllInBatch(), deleteAllByIdInBatch(), and getReferenceById(). You just declare an interface extending it with your entity and id types; Spring Data creates a proxy implementation at startup via the repository factory, backed by SimpleJpaRepository. You add custom queries with derived method names or @Query. Because it exposes the full CRUD+paging surface, prefer a narrower base (CrudRepository or a plain Repository/fragment) when you want to restrict what callers can do.
code
java · 11 lines// Full JPA toolbox
public interface UserRepository extends JpaRepository<User, Long> {
List<User> findByEmailIgnoreCase(String email);
Page<User> findByActiveTrue(Pageable pageable);
}
// Deliberately narrow surface: only expose two methods, hide delete/saveAll
public interface ReadOnlyAuditRepository extends Repository<AuditLog, Long> {
Optional<AuditLog> findById(Long id);
List<AuditLog> findAll();
}go deeper
Know that you extend JpaRepository<Entity, IdType> and get CRUD + paging for free.
Name the layers (Crud/ListCrud/PagingAndSorting) and the JPA-only extras JpaRepository adds.
Explain SimpleJpaRepository/proxy generation and choosing a narrower base to restrict the API surface.
Discuss API-surface leakage, the 3.0 decoupling of paging from CRUD, and repository interface design across a codebase.
**The problem it solves.** A repository is the object that reads and writes entities to the database. Writing one by hand means boilerplate: an EntityManager, a save method, a findById, paging, etc. Spring Data JPA removes that: you declare an *interface*, and at application startup Spring generates a concrete implementation (a dynamic proxy) for you. **The hierarchy (Spring Data 3.x / Spring Boot 3).** From the bottom up: - `Repository<T,ID>` — an empty marker interface. Extending it makes a type a Spring Data repository; you can add just the methods you want. - `CrudRepository<T,ID>` — generic CRUD: `save`, `saveAll`, `findById`, `existsById`, `findAll`, `count`, `deleteById`, `delete`, `deleteAll`. Collection methods return `Iterable`. - `ListCrudRepository<T,ID>` — added in Spring Data 3.0; same as CrudRepository but `findAll`/`saveAll` return `List` instead of `Iterable`, which is more convenient. - `PagingAndSortingRepository<T,ID>` — adds `findAll(Pageable)` and `findAll(Sort)`. **Note:** in Spring Data 3.0 this no longer extends CrudRepository — paging/sorting and CRUD are separate axes now. - `ListPagingAndSortingRepository<T,ID>` — List-returning variant. - `JpaRepository<T,ID>` — the JPA-specific top interface. It extends `ListCrudRepository`, `ListPagingAndSortingRepository`, and `QueryByExampleExecutor`, and adds JPA-only methods. **JPA-only methods JpaRepository adds:** `flush()` (push pending changes to the DB now), `saveAndFlush(entity)` and `saveAllAndFlush(...)`, `deleteAllInBatch()` / `deleteAllInBatch(Iterable)` / `deleteAllByIdInBatch(Iterable)` (bulk deletes in a single statement), and `getReferenceById(id)` (return a lazy reference/proxy without hitting the DB). `getById`/`getOne` are deprecated aliases of `getReferenceById`. **How the implementation is created.** The default backing class is `SimpleJpaRepository`, wired by `JpaRepositoryFactory`. `@EnableJpaRepositories` (auto-configured by Spring Boot) scans for interfaces extending a Spring Data repository and registers a proxy bean for each. So you never write `class UserRepositoryImpl` for standard methods. **Declaring one.** ```java public interface UserRepository extends JpaRepository<User, Long> { List<User> findByEmail(String email); // derived query @Query("select u from User u where u.active = true") List<User> findActive(); // explicit JPQL } ``` **When to extend which.** Extend `JpaRepository` when you want the full, convenient JPA toolbox. Extend `CrudRepository`/`ListCrudRepository` when you don't need paging or JPA batch operations. Extend the bare `Repository<T,ID>` (or compose a fragment) when you deliberately want to expose only a couple of methods and hide the rest — e.g., a read-only repository that must not offer `deleteAll`. **Gotchas.** (1) The generic parameters are `<EntityType, IdType>`; the id type must match the `@Id` field's type or you get a startup error. (2) Extending JpaRepository leaks the entire CRUD+batch+paging API to every caller — that is a design decision, not a free lunch. (3) Repository methods are not transactional-by-default in the way people assume: SimpleJpaRepository methods carry their own `@Transactional`, but multi-step service logic should own the transaction at the service layer.
- Who writes the implementation of UserRepository, and when?Spring Data does, at application startup. @EnableJpaRepositories triggers the JpaRepositoryFactory to create a proxy bean per interface, backed by SimpleJpaRepository, so no hand-written impl is needed for standard methods.
- In Spring Data 3.0, does PagingAndSortingRepository still extend CrudRepository?No. They were decoupled — paging/sorting and CRUD are now independent interfaces. JpaRepository pulls both in (via ListPagingAndSortingRepository and ListCrudRepository) so you still get everything.
saying these in an interview costs you the question
- Claiming you must write a *RepositoryImpl class for basic CRUD
- Thinking JpaRepository is the only base you can extend
- Believing findAll on JpaRepository returns Iterable (it returns List)