skip to content

Query-Derivation Engine

The PartTree parser turns a method name like findByLastNameAndAgeGreaterThan into a query, using a fixed keyword vocabulary. Interviewers ask where derivation stops being readable and you should switch to an explicit query.

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

questions

5

What are derived query methods in Spring Data, and how does a method name like findByLastName become a query?

level: juniorimportance: must knowfreq 72%

answer

  1. no body, name = query
  2. subject (findBy/countBy...) + predicate
  3. args bind positionally L->R
  4. bad property => startup failure
  5. PartTree in Commons

basics

~10 s

You declare a method on a repository interface, like findByLastName(String name), and write no body. Spring Data reads the method name and generates the query automatically from it.

solid answer

~40 s

Derived (query) methods let you declare a repository method with no implementation and let Spring Data build the query from the method name. A method such as findByLastName(String lastName) is parsed into a subject (findBy — return matching entities) and a predicate (LastName — filter on the lastName property). Spring Data's PartTree engine splits the name, maps each fragment to an entity property, and binds the method arguments to the criteria in order. You never write SQL/JPQL for these. The mechanism lives in Spring Data Commons, so the same naming rules apply across stores (JPA, Mongo, etc.); only the emitted query differs. It works best for simple lookups; complex logic should use an explicit @Query or a hand-written method instead.

code

java · 13 lines
java
public interface CustomerRepository extends CrudRepository<Customer, Long> {

    // find + By => return matching entities; LastName => filter on customer.lastName
    List<Customer> findByLastName(String lastName);

    // two criteria, arguments bound positionally: 1st -> lastName, 2nd -> firstName
    List<Customer> findByLastNameAndFirstName(String lastName, String firstName);

    // subject 'countBy' returns a count instead of entities
    long countByLastName(String lastName);

    // no body anywhere: the name IS the query
}

go deeper

for a junior

Must know that the method name generates the query and you write no body.

for a middle

Should explain subject vs predicate split and positional argument binding.

for a senior

Should note startup validation, return-type variety, and PartTree living in Commons.

for a principal

Frames derivation as a fail-fast convenience layer with hard expressiveness limits.

**The idea.** A Spring Data repository is an interface you declare but never implement. Besides the CRUD methods you inherit (from `CrudRepository`/`Repository`), you can add *derived query methods*: methods whose *name* encodes the query. At startup Spring Data creates a proxy for the interface; for each declared method it decides how to answer it, and for a derived method it parses the name and builds a store query — you write zero query code and zero method body. **Anatomy of the name.** A method name splits into two parts: - **Subject / introducing clause** — the leading verb: `findBy`, `readBy`, `getBy`, `queryBy`, `searchBy`, `streamBy` (all mean *return matching entities*), plus `countBy` (return a count), `existsBy` (return boolean), and `deleteBy`/`removeBy` (delete matching rows). Everything up to the first `By` is the subject. - **Predicate / criteria** — everything after `By`. `LastName` in `findByLastName` names the entity's `lastName` property. **Argument binding.** Method parameters are bound to the predicate *positionally, left to right*. `findByLastNameAndFirstName(String last, String first)` binds the first argument to `lastName` and the second to `firstName`. There is no name matching by default — order matters. **Property resolution.** Each predicate fragment must resolve to a real property on the entity (or a nested path like `AddressCity`). If a fragment doesn't map to any property, Spring Data throws at *startup* (e.g. `PropertyReferenceException`) — a key benefit: typos fail fast rather than at query time. **When it works well vs. not.** Derived methods shine for straightforward equality/comparison lookups. Once the name grows unreadable, or you need joins, grouping, projections, or DB functions, prefer an explicit `@Query` or a custom implementation. The parser has finite vocabulary; it cannot express arbitrary SQL. **Return types.** `findBy…` can return a single entity, `Optional<T>`, a `List<T>`, a `Stream<T>`, a `Page<T>`/`Slice<T>` (with a `Pageable` argument), etc. `countBy…` returns `long`, `existsBy…` returns `boolean`. **Where it lives.** The parsing engine is `PartTree` in Spring Data *Commons* (`org.springframework.data.repository.query.parser`), so the naming grammar is shared across all Spring Data modules; each module supplies the store-specific translation of the parsed tree.

  • What happens if you name a property that doesn't exist, e.g. findByLastNam?
    The repository fails to initialize at application startup with a PropertyReferenceException — derivation is validated eagerly, not at query time.
  • Do the method parameter names have to match the property names?
    No. By default parameters bind positionally to the predicate parts in order. Names are irrelevant unless you switch to named parameters with @Param on an explicit @Query.

saying these in an interview costs you the question

  • Thinking you must write the method body or SQL for derived methods.
  • Believing parameters match properties by name instead of by position.
  • Assuming a misspelled property fails silently at runtime rather than at startup.

context

open as a page

Explain the derived-query keywords And, Or, Between, Like, In, IsNull, and OrderBy, and how they combine into a predicate.

level: middleimportance: must knowfreq 58%

basics

~10 s

And/Or combine conditions; Between matches a range (two args); Like does pattern matching; In matches a collection; IsNull checks for null (no arg); OrderBy sorts results, e.g. OrderByAgeDesc.

open as a page

How does Spring Data decide between deriving a query from the method name and using a hand-written query? Explain QueryLookupStrategy.

level: seniorimportance: should knowfreq 33%

basics

~10 s

It depends on the QueryLookupStrategy. By default (CREATE_IF_NOT_FOUND) Spring first looks for a declared query (an @Query annotation or a named query); if none exists, it derives the query from the method name.

open as a page

How does the PartTree engine parse a repository method name? Walk through subject vs. predicate and the findBy/countBy/existsBy/deleteBy verbs.

level: seniorimportance: should knowfreq 34%

basics

~20 s

PartTree splits the name at the first By into a subject (the verb: find/count/exists/delete) and a predicate. It then breaks the predicate on Or into OR-parts and each on And into Parts, mapping every Part to a property and keyword.

open as a page

As a tech lead, when do you push back on derived query methods, and what are the design tradeoffs versus explicit queries?

level: principalimportance: nice to knowfreq 20%

basics

~20 s

Use derivation for simple, readable lookups. Push back when method names get long or need joins, grouping, functions, or complex OR logic — those belong in an explicit @Query or a custom fragment, which are clearer and testable.

open as a page