18
18
import jakarta .persistence .EntityManager ;
19
19
import jakarta .persistence .Query ;
20
20
21
+ import java .lang .reflect .Constructor ;
22
+ import java .lang .reflect .InvocationTargetException ;
23
+
24
+ import org .springframework .data .domain .Pageable ;
25
+ import org .springframework .data .domain .Sort ;
26
+ import org .springframework .data .jpa .repository .QueryRewriter ;
21
27
import org .springframework .data .repository .query .QueryMethodEvaluationContextProvider ;
22
28
import org .springframework .data .repository .query .ResultProcessor ;
23
29
import org .springframework .data .repository .query .ReturnedType ;
35
41
* @author David Madden
36
42
* @author Mark Paluch
37
43
* @author Diego Krupitza
44
+ * @author Greg Turnquist
38
45
*/
39
46
abstract class AbstractStringBasedJpaQuery extends AbstractJpaQuery {
40
47
@@ -43,6 +50,7 @@ abstract class AbstractStringBasedJpaQuery extends AbstractJpaQuery {
43
50
private final QueryMethodEvaluationContextProvider evaluationContextProvider ;
44
51
private final SpelExpressionParser parser ;
45
52
private final QueryParameterSetter .QueryMetadataCache metadataCache = new QueryParameterSetter .QueryMetadataCache ();
53
+ private final QueryRewriter queryRewriter ;
46
54
47
55
/**
48
56
* Creates a new {@link AbstractStringBasedJpaQuery} from the given {@link JpaQueryMethod}, {@link EntityManager} and
@@ -74,6 +82,7 @@ public AbstractStringBasedJpaQuery(JpaQueryMethod method, EntityManager em, Stri
74
82
method .isNativeQuery ());
75
83
76
84
this .parser = parser ;
85
+ this .queryRewriter = findQueryRewriter (method );
77
86
78
87
Assert .isTrue (method .isNativeQuery () || !query .usesJdbcStyleParameters (),
79
88
"JDBC style parameters (?) are not supported for JPA queries." );
@@ -86,7 +95,8 @@ public Query doCreateQuery(JpaParametersParameterAccessor accessor) {
86
95
.applySorting (accessor .getSort (), query .getAlias ());
87
96
ResultProcessor processor = getQueryMethod ().getResultProcessor ().withDynamicProjection (accessor );
88
97
89
- Query query = createJpaQuery (sortedQueryString , processor .getReturnedType ());
98
+ Query query = createJpaQuery (sortedQueryString , accessor .getSort (), accessor .getPageable (),
99
+ processor .getReturnedType ());
90
100
91
101
QueryParameterSetter .QueryMetadata metadata = metadataCache .getMetadata (sortedQueryString , query );
92
102
@@ -137,7 +147,8 @@ public DeclaredQuery getCountQuery() {
137
147
* Creates an appropriate JPA query from an {@link EntityManager} according to the current {@link AbstractJpaQuery}
138
148
* type.
139
149
*/
140
- protected Query createJpaQuery (String queryString , ReturnedType returnedType ) {
150
+ protected Query createJpaQuery (String queryString , Sort sort , @ Nullable Pageable pageable ,
151
+ ReturnedType returnedType ) {
141
152
142
153
EntityManager em = getEntityManager ();
143
154
@@ -148,7 +159,42 @@ protected Query createJpaQuery(String queryString, ReturnedType returnedType) {
148
159
Class <?> typeToRead = getTypeToRead (returnedType );
149
160
150
161
return typeToRead == null //
151
- ? em .createQuery (queryString ) //
152
- : em .createQuery (queryString , typeToRead );
162
+ ? em .createQuery (potentiallyRewriteQuery (queryString , sort , pageable )) //
163
+ : em .createQuery (potentiallyRewriteQuery (queryString , sort , pageable ), typeToRead );
164
+ }
165
+
166
+ /**
167
+ * Useing the {@link org.springframework.data.jpa.repository.QueryRewrite} annotation, look for a
168
+ * {@link QueryRewriter} and instantiate one.
169
+ *
170
+ * @param method - {@link JpaQueryMethod} that has the annotation details
171
+ * @return a {@link QueryRewriter for the method or {@code null}
172
+ */
173
+ @ Nullable
174
+ protected QueryRewriter findQueryRewriter (JpaQueryMethod method ) {
175
+
176
+ Class <? extends QueryRewriter > queryRewriter = method .getQueryRewriter ();
177
+
178
+ if (queryRewriter == null ) {
179
+ return null ;
180
+ }
181
+
182
+ try {
183
+ return (QueryRewriter ) ((Constructor <?>) queryRewriter .getDeclaredConstructor ()).newInstance ();
184
+ } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e ) {
185
+ System .out .println (e );
186
+ return null ;
187
+ }
188
+ }
189
+
190
+ protected String potentiallyRewriteQuery (String originalQuery , Sort sort , @ Nullable Pageable pageable ) {
191
+
192
+ if (this .queryRewriter == null ) {
193
+ return originalQuery ;
194
+ }
195
+
196
+ return pageable != null && pageable .isPaged () //
197
+ ? this .queryRewriter .rewrite (originalQuery , pageable ) //
198
+ : this .queryRewriter .rewrite (originalQuery , sort );
153
199
}
154
200
}
0 commit comments