Projection
About
Projection in JPA allows us to retrieve partial data from a table/entity rather than fetching the entire entity object. This is especially useful when:
We don't need all fields (reduces memory/IO).
We want to optimize performance.
We want to shape our response objects differently than the entity structure.
Instead of returning full entities like Employee
, we can return just names, or a combination of selected fields.
Why Use Projection?
Performance: Avoids unnecessary fetching of unused fields (especially large blobs, associations).
Encapsulation: Returns only relevant data to API clients.
Shaping Results: Can transform or aggregate data in custom structures.
Avoid Lazy Loading Issues: Does not rely on full entity graphs.
Types of Projections in Spring Data JPA
Spring Data JPA supports multiple ways to extract partial data from entities using projections. This is helpful when:
We want to optimize query performance.
We only need a subset of fields from a table.
We need to return data in a custom structure for API responses or UI consumption.
1. Interface-based Projections
Interface-based projections use Java interfaces to retrieve specific fields from entities. Spring Data JPA will dynamically generate proxy implementations for the interface and only fetch the selected properties from the database.
How it works
We define a Java interface with getter methods that match the entity's field names. When we call the repository method, Spring returns proxies that only populate the specified fields.
Example
Characteristics
Must match field names from the entity.
No need to write any query if method names follow Spring Data conventions.
Proxy instances returned, not full entities.
Advantages
Lightweight and easy to write.
Automatically handled by Spring Data.
Efficient: only required columns are selected.
Limitations
Cannot define business logic.
Cannot be used when transformations or computations are needed.
Difficult to use for nested or derived fields (requires closed projection syntax).
2. Class-based Projections (DTOs)
Class-based projections use custom DTO (Data Transfer Object) classes with constructors that accept selected fields. You manually define what you want to retrieve using JPQL or native SQL queries.
How it works
Spring maps results into DTOs using constructor expressions in JPQL. The constructor in the DTO must exactly match the select fields.
Example
Characteristics
Requires constructor with selected fields.
Supports complex logic (can include calculations or nested fields).
Select clause must match constructor exactly.
Advantages
Full control over shape of response.
Works well for complex responses, aggregations, joins.
Supports nested mappings, custom logic in constructor.
Limitations
Requires more code (manual DTO creation).
Must write
new
keyword in JPQL or native queries.Refactoring DTO fields requires updating query as well.
3. Dynamic Projections
Dynamic projections allow us to use a single repository method and dynamically pass the projection type (interface or DTO) at runtime.
How it works
The repository method accepts a Class<T>
parameter, and Spring determines the result type dynamically. It still uses interface- or class-based projection logic under the hood.
Example
Characteristics
Generic method supporting multiple return types.
Useful in APIs where clients choose which view they want.
Can be used with both interfaces and DTOs.
Advantages
Single repository method to support multiple projections.
Reduces duplication of repository methods.
Makes API flexible (e.g., mobile and web clients can request different views).
Limitations
Does not work well with custom JPQL queries (unless separate queries are defined).
You must manage query compatibility manually.
Not suitable when result sets vary too much between projections.
4. Nested/Closed Projections
Nested (also known as closed projections) are projections that access properties of associated (nested) entities using nested interfaces.
How it works
Spring will join the necessary tables and populate the nested fields if you define sub-projection interfaces for related entities. This only works with interface-based projections.
Example
Characteristics
Only works with interface-based projections.
Uses getter-based navigation to access nested fields.
Requires associations to be navigable in JPA (e.g.,
@ManyToOne
,@OneToOne
).
Advantages
Allows you to drill into nested objects cleanly.
Efficient: generates optimized SQL with joins.
No need for custom queries.
Limitations
No support for nested DTOs.
Cannot apply transformations or logic.
Only works when property names match exactly.
5. Open Projections (SpEL)
Open projections use SpEL (Spring Expression Language) inside interface getters to compute values dynamically at runtime from the entity fields.
How it works
Spring will evaluate the @Value
expression at runtime and inject the result. This allows simple data transformation logic in the projection layer.
Example
Characteristics
Based on Spring Expression Language.
Only works with interface-based projections.
Computation happens in memory after query result.
Advantages
Supports simple dynamic transformations.
Easy for quick custom display logic.
Limitations
SpEL expressions evaluated in memory (not in DB).
Less efficient than DTO-based projections.
Cannot be used in large or performance-critical operations.
Difficult to debug and error-prone.
How Projection Works Internally ?
Spring Data inspects the return type of your repository method. Based on the type:
For interface-based, it uses JDK proxies to create dynamic implementations.
For DTOs, it rewrites the JPQL to use
new
constructor syntax.For dynamic projections, it uses runtime type dispatching.
It does not load the entire entity and filter afterward—it changes the SQL/JPQL select clause to only fetch requested columns.
Caveats and Limitations
Interface-based
Yes (closed only)
No
Yes
Lightweight and good for flat data
Class-based (DTO)
Yes
Yes
Yes
Most flexible and maintainable
Open Projections (SpEL)
No
Yes (via SpEL)
No
Not recommended
Dynamic Projections
Depends on usage
Depends
Yes
Great for API flexibility
Best Practices
Use interface-based projections for simple read-only use cases with flat or slightly nested data.
Use DTO projections for complex transformations, joins, or computations.
Use dynamic projections in APIs where clients can choose what to fetch.
Avoid open projections in large-scale or critical systems.
Use closed projections when we need to traverse related entities in a clean, typed way.
Last updated
Was this helpful?