Spring Data Specifications for Dynamic Queries
Fast recall
Quick revision
Core answer
Predicate — one filter per Specification, composed at runtime with .and(), .or(), .not(). Repositories that extend `JpaSpecificationExecutorfindAll(Specification, Pageable), count, and findOne methods. The win is killing the combinatorial explosion of derived methods for search forms — instead of findByStatus, findByStatusAndCity, findByStatusAndDate, … you have one findAll(spec) built from only the filters provided. Returning null is idiomatic for an empty filter. Generated SQL is always parameterized — safe from injection by construction. Trade-offs vs QueryDSL: Specifications are terser than raw Criteria but more verbose than QueryDSL's Q-classes; QueryDSL has superior compile-time type safety; Specifications win on zero extra build setup.Whether the candidate knows alternatives to writing dozens of `findBy*And*Or*` methods for complex filter UIs
Writing separate `findByStatusAndDateAndCity()`, `findByStatusAndDate()`, `findByDate()` methods for every combination — unmaintainable past three filters
Compare Specifications against QueryDSL, mention the JPA metamodel for type-safe field references, and note that the generated SQL is always parameterized
Interview-ready guide
Interview answer
Specifications solve the dynamic query problem — building a WHERE clause where filters are optional and combinations depend on runtime input.
The pattern:
- Each filter is a
Specification— a lambda returning aPredicate - Compose with
Specification.where(hasStatus(status)).and(inCity(city)).and(after(date)) nullpredicates are ignored — ifstatusis null,hasStatus(null)returnsnulland the chain skips it
Implementation:
- Add
JpaSpecificationExecutorto the repository - Define static factories returning
Specification - Call
orderRepo.findAll(spec, pageable)— pagination and sorting work transparently
vs QueryDSL:
- QueryDSL generates a
QOrderclass from the entity at compile time QOrder.order.status.eq(status).and(QOrder.order.city.eq(city))— fluent and type-safe- More powerful for path traversal; needs an annotation processor and Q-class generation step
When to switch:
- Past ~10 filter methods, string field names cause production typos
- Need compile-time validation — adopt QueryDSL or the JPA metamodel
Spring Data Specifications for Dynamic Queries
Direct Answer
Specification<T> is a functional interface returning a JPA Predicate — one filter per Specification, composed at runtime with .and(), .or(), .not(). Repositories that extend JpaSpecificationExecutor<T> gain findAll(Specification, Pageable), count, and findOne methods. The win is killing the combinatorial explosion of derived methods for search forms — instead of findByStatus, findByStatusAndCity, findByStatusAndDate, … you have one findAll(spec) built from only the filters provided. Returning null is idiomatic for an empty filter. Generated SQL is always parameterized — safe from injection by construction. Trade-offs vs QueryDSL: Specifications are terser than raw Criteria but more verbose than QueryDSL's Q-classes; QueryDSL has superior compile-time type safety; Specifications win on zero extra build setup.
Common Mistakes & Pitfalls
Writing separate findByStatusAndDateAndCity(), findByStatusAndDate(), findByDate() methods for every combination — unmaintainable past three filters
Check your understanding
Answer these without looking back at the article.
- How do you handle pagination and sorting when using Specifications?
- What is the difference between Specifications and QueryDSL — when would you choose one over the other?
- How do you write a Specification that filters based on a child collection (orders containing a specific product)?
- How does the JPA metamodel help, and why is it not always worth the build cost?
Related interview prep categories
2Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.