Skip to content

Commit 7f13a04

Browse files
committed
Polishing.
Refine projection documentation. See #2757
1 parent 7998ec7 commit 7f13a04

File tree

2 files changed

+29
-28
lines changed

2 files changed

+29
-28
lines changed

src/main/antora/antora-playbook.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ content:
1717
- url: https://github.com/spring-projects/spring-data-commons
1818
# Refname matching:
1919
# https://docs.antora.org/antora/latest/playbook/content-refname-matching/
20-
branches: [main, 3.2.x]
20+
branches: [ main, 3.4.x ]
2121
start_path: src/main/antora
2222
asciidoc:
2323
attributes:

src/main/antora/modules/ROOT/pages/repositories/projections.adoc

+28-27
Original file line numberDiff line numberDiff line change
@@ -3,41 +3,42 @@
33

44
:projection-collection: Collection
55

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

8-
NOTE: It is important to note that <<projections.dtos,Class-based projections>> with JPQL is limited to *constructor expressions* in your JPQL expression, e.g. `SELECT new com.example.NamesOnly(u.firstname, u.lastname) from User u`.
9-
(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.
10-
And it's important to point out that class-based projections do not work with native queries AT ALL.
11-
As a workaround you may use named queries with `ResultSetMapping` or the Hibernate-specific javadoc:{hibernatejavadocurl}org.hibernate.query.ResultListTransformer[]
8+
include::{commons}@data-commons::page$repositories/projections-intro.adoc[leveloffset+=1]
9+
10+
include::{commons}@data-commons::page$repositories/projections-interface.adoc[leveloffset=2]
11+
12+
include::{commons}@data-commons::page$repositories/projections-class.adoc[leveloffset=2]
13+
14+
== Using Projections with JPA
1215

13-
include::{commons}@data-commons::page$repositories/projections-interface.adoc[leveloffset=1]
16+
You can use Projections with JPA in several ways.
17+
Depending on the technique and query type, you need to apply specific considerations.
1418

15-
include::{commons}@data-commons::page$repositories/projections-class.adoc[leveloffset=1]
19+
Spring Data JPA uses generally `Tuple` queries to construct interface proxies for <<projections.interfaces,Interface-based Projections>>.
1620

21+
=== Derived queries
1722

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

19-
[NOTE]
20-
====
21-
<<projections.dtos,Class-based projection (DTO projections)>> types must declare a single constructor so that Spring Data can determine its input properties.
22-
If your class defines more than one constructor, then you cannot use the type without further hints for DTO projections.
23-
In such a case annotate the desired constructor with `@PersistenceCreator` as outlined below so that Spring Data can determine which properties to select:
26+
Projections limit the selection to top-level properties of the target entity.
27+
Any nested properties resolving to joins select the entire nested property causing the full join to materialize.
2428

25-
[source,java]
26-
----
27-
public class NamesOnly {
29+
=== String-based queries
2830

29-
private final String firstname;
30-
private final String lastname;
31+
Support for string-based queries covers both, JPQL queries(`@Query`) and native queries (`@NativeQuery`).
32+
33+
==== JPQL Queries
34+
35+
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`.
36+
(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.
37+
As a workaround you may use named queries with `ResultSetMapping` or the Hibernate-specific javadoc:{hibernatejavadocurl}org.hibernate.query.ResultListTransformer[]
3138

32-
protected NamesOnly() { }
39+
==== Native Queries
3340

34-
@PersistenceCreator
35-
public NamesOnly(String firstname, String lastname) {
36-
this.firstname = firstname;
37-
this.lastname = lastname;
38-
}
41+
When using <<projections.dtos,Class-based projections>>, their usage requires slightly more consideration depending on your :
3942

40-
// ...
41-
}
42-
----
43-
====
43+
* 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).
44+
* 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 = "…")`.

0 commit comments

Comments
 (0)