DTO Projections in Spring Data JPA
Fast recall
Quick revision
Core answer
SELECT new com.x.OrderSummary(o.id, o.status, c.name) or Java records (explicit, type-safe, JPQL or native); dynamic projections — List findByStatus(OrderStatus s, Class type) — the caller chooses the projection at runtime. Trap: open projections (@Value("#{target.firstName + ' ' + target.lastName}")) LOOK like optimization but actually load the full entity and evaluate SpEL in Java. Closed projections (getters matching entity properties exactly) generate efficient SQL. Nested association getters (getCustomer() returning another interface) trigger N+1 — use a flattened class-based DTO instead.Whether the candidate knows how to optimise read queries and avoid the overhead of loading full entities when only a subset of fields is needed
Using interface projections with associations triggers N+1 because Spring Data fetches each related entity separately. Closed projections (matching exact column names) are more efficient than open projections
Explain the difference between open and closed projections, discuss the @Value SpEL-based computed properties in interface projections, and mention dynamic projections using a generic <T> return type
Interview-ready guide
Interview answer
DTO projections let you select exactly the data your query needs without loading full entities. Reduces data transferred and prevents lazy-loading issues in read paths.
Interface projections:
- Define an interface with getter methods matching entity fields
- Change the repository return type — Spring generates
SELECT id, status FROM orders - Closed projection (method name = field name): only those columns selected
- Open projection (
@Value("#{target...}")): loads full entity, evaluates SpEL — no column optimization
Class-based projections:
@Query("SELECT new com.example.OrderDto(o.id, o.status, o.total) FROM Order o ...")- Constructor expression — Hibernate calls the DTO constructor; no entity, no proxy
- Works with native queries and complex joins
Association trap:
interface OrderSummary { CustomerView getCustomer(); }— Spring proxies the nested interface; accessingcustomer.getName()fires a query per row- Use a flattened class-based DTO with
customerNameinstead
When to use: list views, read-heavy endpoints, and any query where you do not need entity management.
DTO Projections in Spring Data JPA
Direct Answer
DTO projections let Spring Data JPA fetch only the columns a query needs instead of materializing full entities. Three styles: interface-based closed projections (interface with getters matching entity field names — Spring generates a SELECT with exactly those columns, no entity, no lazy proxies); class-based projections via SELECT new com.x.OrderSummary(o.id, o.status, c.name) or Java records (explicit, type-safe, JPQL or native); dynamic projections — <T> List<T> findByStatus(OrderStatus s, Class<T> type) — the caller chooses the projection at runtime. Trap: open projections (@Value("#{target.firstName + ' ' + target.lastName}")) LOOK like optimization but actually load the full entity and evaluate SpEL in Java. Closed projections (getters matching entity properties exactly) generate efficient SQL. Nested association getters (getCustomer() returning another interface) trigger N+1 — use a flattened class-based DTO instead.
Common Mistakes & Pitfalls
Using interface projections with associations triggers N+1 because Spring Data fetches each related entity separately. Closed projections (matching exact column names) are more efficient than open projections
Check your understanding
Answer these without looking back at the article.
- What is the difference between a closed and an open interface projection in terms of the SQL generated?
- Can you use DTO projections with native SQL queries in Spring Data JPA?
- How does a class-based projection with a Java record differ from using a custom JPQL @Query that returns Object[]?
- How do dynamic projections interact with `Page<T>` results?
Related interview prep categories
2Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.