skip to content

Spring Data JPA

The JPA-flavoured repository module: JpaRepository, derived queries, @Query with JPQL or native SQL, entity graphs, locking, Specifications and stored procedures. Most Java backend interviews spend real time here, because most Java backends persist through it.

part ofSpring Frameworkoverview, primer and where to startread it →
on this pageshow

explore

questions

page 1 of 2

What are JPA derived query methods, and how do keywords like IgnoreCase and OrderBy shape the generated query?

level: juniorimportance: must knowfreq 75%

answer

  1. Query from the method name
  2. prefix + criteria + IgnoreCase + OrderBy
  3. params bind positionally
  4. PropertyReferenceException at startup
  5. UPPER() can kill the index

basics

~10 s

Derived queries let Spring Data JPA build a SQL/JPQL query from the method NAME. E.g. findByEmailIgnoreCase compares email case-insensitively; adding OrderByNameAsc sorts results by name ascending. No @Query needed.

solid answer

~40 s

A derived query method is a repository method whose name Spring Data JPA parses into a query at startup. The parser strips a subject prefix (findBy, readBy, getBy, queryBy), then reads a criteria expression built from property names joined by And/Or, plus keywords: IgnoreCase for a single property, AllIgnoreCase for the whole expression, and an OrderBy...Asc/Desc clause for sorting. Method parameters bind positionally to the criteria. So findByLastNameIgnoreCaseAndActiveTrueOrderByCreatedAtDesc('smith') generates WHERE UPPER(last_name)=UPPER(?) AND active=true ORDER BY created_at DESC. The names must map to real entity properties or the app fails fast on startup. It removes boilerplate for simple lookups; complex logic should move to @Query.

code

java · 11 lines
java
public interface UserRepository extends JpaRepository<User, Long> {

    // WHERE UPPER(email) = UPPER(?1)
    Optional<User> findByEmailIgnoreCase(String email);

    // WHERE last_name = ?1 AND active = true ORDER BY created_at DESC
    List<User> findByLastNameAndActiveTrueOrderByCreatedAtDesc(String lastName);

    // AllIgnoreCase applies to every String criterion
    List<User> findByFirstNameAndLastNameAllIgnoreCase(String first, String last);
}

go deeper

for a junior

Know that the method name generates the query and that IgnoreCase/OrderBy are name keywords.

for a middle

Explain positional parameter binding and fail-fast PropertyReferenceException at startup.

for a senior

Discuss AllIgnoreCase vs IgnoreCase, return-type semantics, and the UPPER() index impact.

for a principal

Weigh derived-method readability limits vs @Query/Specifications and normalized-column strategies for case-insensitive search at scale.

## What it is Spring Data JPA can implement a repository method purely from its NAME — you declare the signature, Spring writes the query. These are called **derived query methods** (or query-derivation). ## Anatomy of the name `findByLastNameIgnoreCaseOrderByCreatedAtDesc` 1. **Subject / prefix** — `findBy`, `readBy`, `getBy`, `queryBy`, `searchBy`, `streamBy` all mean the same 'select' intent. `existsBy`, `countBy`, `deleteBy`/`removeBy` change the operation. 2. **Criteria** — property names (`LastName`) combined with `And` / `Or`, each optionally followed by an operator keyword (`Like`, `Between`, `GreaterThan`, `In`, `True`, `Null`, etc.). Bare property means equality. 3. **`IgnoreCase`** — placed right after a String property, wraps both sides in `UPPER(...)` so the comparison is case-insensitive: `findByEmailIgnoreCase`. **`AllIgnoreCase`** at the end applies it to every String criterion. 4. **`OrderBy...Asc/Desc`** — static sort baked into the method: `OrderByCreatedAtDesc`. You can also sort dynamically instead by adding a `Sort` parameter. ## How parameters bind Parameters bind **positionally, left to right**, to the criteria in the name. `findByFirstNameAndLastName(String first, String last)` — first param → FirstName, second → LastName. Count and order must match or startup fails. ## Fail-fast Spring parses every derived method when the `EntityManagerFactory`/repository bean initializes. A typo like `findByEmial` that doesn't map to a property throws `PropertyReferenceException` at startup, not at runtime — a key safety benefit. ## Return types `find...` can return the entity, `Optional<T>`, `List<T>`, `Stream<T>`, `Page<T>`, `Slice<T>`. Returning a single object when multiple rows match throws `IncorrectResultSizeDataAccessException`. ## When to use / stop Great for simple, stable lookups. Once the name grows past ~2-3 conditions it becomes unreadable — switch to `@Query` (JPQL) or Specifications. `IgnoreCase` on a non-String property throws at startup. ## Gotcha `IgnoreCase` uses `UPPER()`, which can defeat a plain B-tree index on that column unless you have a functional/expression index. For high-volume case-insensitive lookups consider a normalized (already-lowercased) column instead.

  • What happens if you misspell a property name in a derived method?
    The application fails at startup with a PropertyReferenceException when Spring parses the repository — it does not wait until the method is called at runtime.
  • What is the difference between IgnoreCase and AllIgnoreCase?
    IgnoreCase applies to the single preceding String property; AllIgnoreCase, placed at the end, applies case-insensitivity to every String property in the criteria.

saying these in an interview costs you the question

  • Thinking the query is parsed lazily on first call rather than at startup
  • Believing IgnoreCase works on numeric/date properties
  • Assuming derived methods need @Query to sort

context

open as a page

What is @EntityGraph in Spring Data JPA, and what problem does it solve?

level: juniorimportance: must knowfreq 70%

basics

~20 s

@EntityGraph is an annotation you put on a repository method to tell JPA which associations to load eagerly in one query. It fixes the N+1 select problem where each parent triggers an extra query for its children.

open as a page

What is optimistic locking in JPA, and how does the @Version field implement it?

level: juniorimportance: must knowfreq 60%

basics

~10 s

Optimistic locking detects concurrent edits without locking rows. You add a @Version field; Hibernate checks it in the UPDATE's WHERE clause and throws an error if another transaction already changed the row.

open as a page

What is the @Query annotation in Spring Data JPA, and how do you bind parameters to a JPQL query?

level: juniorimportance: must knowfreq 78%

basics

~20 s

@Query lets you write your own query on a repository method instead of relying on the method name. By default it's JPQL. You bind values with named parameters like :name using @Param, or by position with ?1.

open as a page

What is JpaRepository and where does it sit in the Spring Data repository interface hierarchy?

level: juniorimportance: must knowfreq 78%

basics

~10 s

JpaRepository 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.

open as a page

What is Spring Data JPA's Specification mechanism and how do you enable it on a repository?

level: juniorimportance: must knowfreq 65%

basics

~10 s

A Specification is a reusable object holding one query condition (a WHERE predicate). To use it, your repository extends JpaSpecificationExecutor, which adds methods like findAll(Specification) that run those conditions.

open as a page

How do you write a native SQL query with @Query, and what changes compared to JPQL?

level: middleimportance: must knowfreq 70%

basics

~20 s

Set nativeQuery=true on @Query and write real database SQL using table and column names instead of entity fields. It's useful for database-specific features JPQL can't express, but the query is not validated at startup and is less portable.

open as a page

What does saveAndFlush do that save does not, and when would you use flush()?

level: middleimportance: must knowfreq 70%

basics

~10 s

save() stages the change in the persistence context; the SQL may run later. saveAndFlush() saves and immediately runs flush(), forcing the INSERT/UPDATE to the database now — still inside the transaction, not a commit.

open as a page

How do you compose Specifications with and(), or(), and not() to build dynamic filters?

level: middleimportance: must knowfreq 60%

basics

~10 s

Each small Specification is one condition. Combine them with spec1.and(spec2), spec1.or(spec2), and Specification.not(spec). You start from a neutral base and conditionally chain filters that are active, producing one combined WHERE clause.

open as a page

What goes wrong when an @EntityGraph eagerly fetches collections combined with pagination or multiple collections, and how do you handle it?

level: seniorimportance: must knowfreq 50%

basics

~20 s

Fetching two List collections at once throws MultipleBagFetchException. Paginating (Pageable) while join-fetching a collection makes Hibernate load all rows and page in memory (HHH000104 warning). Fix: fetch one collection, use Set for bags, or split into a two-step id-then-fetch query.

open as a page

What are the requirements and pitfalls of returning Stream<T> from a Spring Data JPA repository method?

level: seniorimportance: must knowfreq 45%

basics

~20 s

A repository method can return Stream<T> to read rows lazily one at a time instead of loading them all. You must run it inside an open transaction and close the stream (try-with-resources), because it keeps a database cursor open.

open as a page

What does @Modifying do, and when do you need clearAutomatically and flushAutomatically?

level: seniorimportance: must knowfreq 68%

basics

~20 s

@Modifying marks a @Query as an UPDATE or DELETE (or INSERT native) rather than a SELECT, so Spring calls executeUpdate() and returns the affected-row count. clearAutomatically clears the persistence context after the query so stale cached entities don't hide the change; flushAutomatically flushes pending changes before it runs.

open as a page

How do you call a database stored procedure from a Spring Data JPA repository?

level: juniorimportance: should knowfreq 35%

basics

~10 s

Add a method to your repository and annotate it with @Procedure, giving the stored procedure's name. Spring Data JPA calls that procedure in the database and maps the result to the method's return type.

open as a page

How do Distinct and the First/Top limiting keywords behave in derived query methods?

level: middleimportance: should knowfreq 58%

basics

~10 s

Distinct adds SELECT DISTINCT to remove duplicate rows. First and Top limit how many rows come back: findFirstByOrderByScoreDesc returns one row; findTop10By... returns ten. First and Top are interchangeable.

open as a page

How does nested property traversal work in a derived method, and why does findByAddress_City use an underscore?

level: middleimportance: should knowfreq 60%

basics

~20 s

You can navigate into related entities by camel-casing the path: findByAddressCity reaches the City field of the Address association (a JOIN). If a property name is ambiguous, an underscore (findByAddress_City) tells Spring exactly where to split the path.

open as a page

How do you declare named vs ad-hoc entity graphs, and how do you fetch nested (multi-level) associations?

level: middleimportance: should knowfreq 55%

basics

~10 s

Ad-hoc: @EntityGraph(attributePaths = {"orders", "orders.items"}) directly on the method. Named: define @NamedEntityGraph on the entity, then reference it with @EntityGraph(value = "..."). Dot notation like "orders.items" fetches nested levels.

open as a page

How do you request a pessimistic lock on a Spring Data repository method, and what's the difference between PESSIMISTIC_READ and PESSIMISTIC_WRITE?

level: middleimportance: should knowfreq 45%

basics

~10 s

Put @Lock(LockModeType.PESSIMISTIC_WRITE) on the repository query method. PESSIMISTIC_READ is a shared lock (others can read, not write); PESSIMISTIC_WRITE is an exclusive lock (SELECT ... FOR UPDATE) that blocks other writers and lockers.

open as a page

What does @QueryHints do on a repository method, and what are the common hints (fetch size, readOnly, cacheable)?

level: middleimportance: should knowfreq 40%

basics

~10 s

@QueryHints attaches JPA/Hibernate query hints to a repository query — like JDBC fetch size, marking results read-only, or enabling the query cache. It tunes how the query executes without changing what it returns.

open as a page

What are the trade-offs between named parameters, positional parameters, and safe binding in @Query, and how do you avoid injection?

level: middleimportance: should knowfreq 55%

basics

~20 s

Named parameters (:name with @Param) are readable and refactor-safe; positional parameters (?1, ?2) are terser but tied to argument order. Both are bound safely by the driver, which prevents injection. Never concatenate user input into the query string.

open as a page

What does getReferenceById return, and how does it differ from findById?

level: middleimportance: should knowfreq 55%

basics

~10 s

getReferenceById returns a lazy proxy without querying the database; it only loads when you access a real property. findById runs a SELECT immediately and returns an Optional with the fully loaded entity (or empty).

open as a page

Show how to build reusable, null-safe Specification factory methods for an optional-filter search, and explain the null-predicate contract.

level: middleimportance: should knowfreq 40%

basics

~10 s

Write static methods returning Specification<T>. Each checks its input: if the filter value is null, return a lambda whose toPredicate returns null (no restriction); otherwise build the predicate. Compose the active ones with and().

open as a page

What do the existsBy, countBy, and deleteBy derived prefixes do, and what must you add for derived deletes to work correctly?

level: seniorimportance: should knowfreq 55%

basics

~10 s

existsBy returns a boolean (efficient existence check), countBy returns a long count, and deleteBy/removeBy delete matching rows. Derived deletes are modifying queries, so they must run inside a transaction (@Transactional).

open as a page

Explain the difference between EntityGraphType.FETCH and EntityGraphType.LOAD.

level: seniorimportance: should knowfreq 45%

basics

~10 s

FETCH (the default) makes listed attributes EAGER and treats everything not listed as LAZY. LOAD makes listed attributes EAGER but leaves unlisted attributes with their mapped fetch type. FETCH gives a stricter, fully-specified plan.

open as a page

What do LockModeType.OPTIMISTIC and OPTIMISTIC_FORCE_INCREMENT do, and how do they differ from plain @Version behavior?

level: seniorimportance: should knowfreq 30%

basics

~20 s

OPTIMISTIC forces a version check at commit even if you only read the entity (guarding against concurrent changes). OPTIMISTIC_FORCE_INCREMENT additionally bumps the entity's @Version even when the entity itself wasn't modified — useful to signal an aggregate changed.

open as a page

What operational risks come with pessimistic locking (timeouts, deadlocks, held locks), and how do you mitigate them in Spring Data JPA?

level: seniorimportance: should knowfreq 32%

basics

~10 s

Pessimistic locks block other transactions, so you risk long waits, deadlocks, and throughput loss. Mitigate with a jakarta.persistence.lock.timeout query hint, consistent lock ordering, short transactions, and never holding a lock across a user round-trip.

open as a page

How does deleteAllInBatch differ from deleteAll, and what are the consequences?

level: seniorimportance: should knowfreq 48%

basics

~10 s

deleteAll loads each entity and deletes it one-by-one, running JPA lifecycle callbacks and cascades. deleteAllInBatch issues a single bulk 'DELETE FROM entity' JPQL, bypassing the persistence context, cascades, @PreRemove callbacks, and the first-level cache.

open as a page

How do you write a Specification that filters on a joined/associated entity, and how do you avoid duplicate rows and N+1 problems?

level: seniorimportance: should knowfreq 45%

basics

~20 s

Inside toPredicate, call root.join("association") to reach the related entity, then build a predicate on it. A to-many join can duplicate parents, so add query.distinct(true). Use a fetch join or entity graph to avoid N+1 loading.

open as a page

When do the limits of derived query methods force you to switch to @Query, Specifications, or Pageable?

level: principalimportance: should knowfreq 45%

basics

~20 s

Derived methods can only express what fits in a method name: fixed conditions, static sort, and a fixed First/Top limit. Anything needing projections, LEFT joins, subqueries, computed expressions, offset paging, or dynamic optional filters must move to @Query, Pageable, or Specifications/Criteria.

open as a page

When would you choose @EntityGraph over a JPQL JOIN FETCH, @BatchSize, or a DTO projection?

level: principalimportance: should knowfreq 40%

basics

~20 s

Use @EntityGraph for a declarative eager plan on derived/named repository methods without writing JPQL. Use JOIN FETCH when you already write custom JPQL. Use @BatchSize when you page collections or fetch several to-many sides. Use DTO projections when you only need a few fields read-only.

open as a page

How do you decide between optimistic and pessimistic locking for a given operation, and how do you handle the resulting failures gracefully?

level: principalimportance: should knowfreq 26%

basics

~20 s

Use optimistic (@Version) by default — no locks, scales, retry rare conflicts. Use pessimistic (@Lock FOR UPDATE) only for hot, high-contention rows where retries would storm. Handle failures by catching the specific Spring exception and retrying with backoff or reporting a conflict.

open as a page

showing 1–30 of 35