Use Spring Data JPA’s Specification<T> to express a reusable entity predicate, then combine small specifications when building a repository query. Add JpaSpecificationExecutor<T> to the repository to run them. This approach is most useful when filters are optional or their combinations vary; fixed queries are often clearer as derived query methods.
What a Specification represents
A Spring Data JPA Specification<T> expresses a predicate over an entity through the JPA Criteria API. It is a reusable condition—not a complete repository query. Spring describes the API as a focused way to express and reuse predicates, and relates the term to the Specification concept in Eric Evans’ Domain-Driven Design. See the Spring Data JPA Specifications reference and the Specification API documentation.
Set up the repository
Extend the repository with JpaSpecificationExecutor<T> alongside the usual JPA repository interface. The executor provides methods for querying with specifications.
public interface CustomerRepository
extends JpaRepository<Customer, Long>,
JpaSpecificationExecutor<Customer> {
}
Write small, reusable specifications
A specification factory can expose focused predicates for an entity. For example, this factory creates a case-insensitive substring match for a customer’s email:
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minutepublic final class CustomerSpecifications {
private CustomerSpecifications() {}
public static Specification<Customer> emailContains(String text) {
return (root, query, cb) ->
cb.like(cb.lower(root.get("email")), "%" + text.toLowerCase() + "%");
}
public static Specification<Customer> isActive() {
return (root, query, cb) ->
cb.isTrue(root.get("active"));
}
}
The example uses CriteriaBuilder operations rather than concatenating input into a query string. In production, decide how to handle null or blank search text before constructing the predicate, and use locale-aware case normalization if the application’s language requirements call for it.
Combine specifications for a use case
Compose predicates where the application knows which criteria apply, then pass the result to the repository:
Rank #2
Specification<Customer> filter = Specification
.where(CustomerSpecifications.emailContains(searchText))
.and(CustomerSpecifications.isActive());
List<Customer> customers = repository.findAll(filter);
Composition methods include and, or, allOf, and anyOf. In current Spring Data JPA API versions, use Specification.unrestricted() for an optional criterion that is absent; it contributes no predicate and is elided during composition. Check the API version in your project before adopting this method, because older examples may use different nullable-where() patterns.
Specification<Customer> emailFilter = hasEmailCriterion
? CustomerSpecifications.emailContains(searchText)
: Specification.unrestricted();
Specification<Customer> filter = emailFilter
.and(CustomerSpecifications.isActive());
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Choose the query approach that fits
Specifications are particularly useful when the application needs to recombine a set of small predicates across use cases. Other query approaches can be simpler when the query shape is stable or the data access needs are different.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Quick Recap
Best Value
Rank #4
| Approach | Optionality and combinations | Readability and reuse | Joins and SQL control |
|---|---|---|---|
| Specifications | Well suited to optional filters and many changing combinations. | Small predicates can be reused and composed, though many abstractions can make a query harder to follow. | Uses Criteria API; inspect generated SQL for complex joins. Does not guarantee a particular SQL shape or performance. |
| Derived query methods | Best when the set of query conditions is fixed. | Direct and concise for straightforward queries; method names become unwieldy as combinations grow. | Less direct control than writing an explicit query. |
| Query by Example | Useful for matching example-object values, but not a general substitute for arbitrary predicate logic. | Can be approachable for simple, probe-based matching; reuse and expressiveness depend on the query needs. | Does not provide the same explicit Criteria predicate composition. |
| Explicit JPQL or Criteria code | Can express fixed or sophisticated query shapes; dynamic conditions require deliberate construction. | Centralizes query logic, but may be more verbose than composing reusable specifications. | Offers more direct query-shape control; still validate actual generated SQL and database behavior. |
Watch for version and query-shape pitfalls
- Confirm the Spring Data JPA version. The current API documents
unrestricted()and collection composition methods such asallOfandanyOf; do not assume these are available in older dependencies. - Keep predicates focused. Prefer one condition per factory method, and combine them at the use-case boundary so the chosen filters are visible.
- Be deliberate with joins and pagination. Avoid unbounded fetch joins in pageable queries; they can complicate result counts and page boundaries.
- Inspect database behavior. For complex joins or filters, review generated SQL, relevant indexes, and execution plans in the target database. The API does not guarantee a universal speed advantage.
How to tell whether Specifications are the right fit
- Use specifications when users can select different filters and the combinations need to change at runtime.
- Use derived query methods when a small number of fixed predicates keeps the repository readable.
- Consider Query by Example for straightforward matching against a probe object.
- Use explicit JPQL or Criteria code when the query’s structure needs more direct control than reusable predicates provide.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

