[[jpa.projections]]
= Projections

:projection-collection: Collection

== Introduction

include::{commons}@data-commons::page$repositories/projections-intro.adoc[leveloffset+=1]

include::{commons}@data-commons::page$repositories/projections-interface.adoc[leveloffset=2]

include::{commons}@data-commons::page$repositories/projections-class.adoc[leveloffset=2]

== Using Projections with JPA

You can use Projections with JPA in several ways.
Depending on the technique and query type, you need to apply specific considerations.

Spring Data JPA uses generally `Tuple` queries to construct interface proxies for <<projections.interfaces,Interface-based Projections>>.

=== Derived queries

Query derivation supports both, class-based and interface projections by introspecting the returned type.
Class-based projections use JPA's instantiation mechanism (constructor expressions) to create the projection instance.

Projections limit the selection to top-level properties of the target entity.
Any nested properties resolving to joins select the entire nested property causing the full join to materialize.

=== String-based queries

Support for string-based queries covers both, JPQL queries(`@Query`) and native queries (`@NativeQuery`).

==== JPQL Queries

When using <<projections.dtos,Class-based projections>> with JPQL, you must use *constructor expressions* in your JPQL query, e.g. `SELECT new com.example.NamesOnly(u.firstname, u.lastname) from User u`.
(Note the usage of a FQDN for the DTO type!) This JPQL expression can be used in `@Query` annotations as well where you define any named queries.
As a workaround you may use named queries with `ResultSetMapping` or the Hibernate-specific javadoc:{hibernatejavadocurl}org.hibernate.query.ResultListTransformer[]

==== Native Queries

When using <<projections.dtos,Class-based projections>>, their usage requires slightly more consideration depending on your :

* If properties of the result type map directly to the result (the order of columns and their types match the constructor arguments), then you can declare the query result type as the DTO type without further hints (or use the DTO class through dynamic projections).
* If the properties do not match or require transformation, use `@SqlResultSetMapping` through JPA's annotations map the result set to the DTO and provide the result mapping name through `@NativeQuery(resultSetMapping = "…")`.
