@@ -79,6 +79,7 @@ static class QueryBlockBuilder {
79
79
private String queryVariableName = "query" ;
80
80
private @ Nullable AotQueries queries ;
81
81
private MergedAnnotation <QueryHints > queryHints = MergedAnnotation .missing ();
82
+ private @ Nullable AotEntityGraph entityGraph ;
82
83
private @ Nullable String sqlResultSetMapping ;
83
84
private @ Nullable Class <?> queryReturnType ;
84
85
@@ -112,6 +113,11 @@ public QueryBlockBuilder queryHints(MergedAnnotation<QueryHints> queryHints) {
112
113
return this ;
113
114
}
114
115
116
+ public QueryBlockBuilder entityGraph (@ Nullable AotEntityGraph entityGraph ) {
117
+ this .entityGraph = entityGraph ;
118
+ return this ;
119
+ }
120
+
115
121
public QueryBlockBuilder queryReturnType (@ Nullable Class <?> queryReturnType ) {
116
122
this .queryReturnType = queryReturnType ;
117
123
return this ;
@@ -162,7 +168,7 @@ public CodeBlock build() {
162
168
}
163
169
164
170
builder .add (createQuery (queryVariableName , queryStringNameVariableName , queries .result (),
165
- this .sqlResultSetMapping , this .queryHints , this .queryReturnType ));
171
+ this .sqlResultSetMapping , this .queryHints , this .entityGraph , this . queryReturnType ));
166
172
167
173
builder .add (applyLimits (queries .result ().isExists ()));
168
174
@@ -173,7 +179,7 @@ public CodeBlock build() {
173
179
boolean queryHints = this .queryHints .isPresent () && this .queryHints .getBoolean ("forCounting" );
174
180
175
181
builder .add (createQuery (countQueryVariableName , countQueryStringNameVariableName , queries .count (), null ,
176
- queryHints ? this .queryHints : MergedAnnotation .missing (), Long .class ));
182
+ queryHints ? this .queryHints : MergedAnnotation .missing (), null , Long .class ));
177
183
builder .addStatement ("return ($T) $L.getSingleResult()" , Long .class , countQueryVariableName );
178
184
179
185
// end control flow does not work well with lambdas
@@ -190,8 +196,7 @@ private CodeBlock applySorting(String sort, String queryString, Class<?> actualR
190
196
builder .beginControlFlow ("if ($L.isSorted())" , sort );
191
197
192
198
builder .addStatement ("$T declaredQuery = $T.$L($L)" , DeclaredQuery .class , DeclaredQuery .class ,
193
- queries != null && queries .isNative () ? "nativeQuery" : "jpqlQuery" ,
194
- queryString );
199
+ queries != null && queries .isNative () ? "nativeQuery" : "jpqlQuery" , queryString );
195
200
196
201
builder .addStatement ("$L = rewriteQuery(declaredQuery, $L, $T.class)" , queryString , sort , actualReturnType );
197
202
builder .endControlFlow ();
@@ -238,13 +243,17 @@ private CodeBlock applyLimits(boolean exists) {
238
243
239
244
private CodeBlock createQuery (String queryVariableName , @ Nullable String queryStringNameVariableName ,
240
245
AotQuery query , @ Nullable String sqlResultSetMapping , MergedAnnotation <QueryHints > queryHints ,
241
- @ Nullable Class <?> queryReturnType ) {
246
+ @ Nullable AotEntityGraph entityGraph , @ Nullable Class <?> queryReturnType ) {
242
247
243
248
Builder builder = CodeBlock .builder ();
244
249
245
250
builder .add (
246
251
doCreateQuery (queryVariableName , queryStringNameVariableName , query , sqlResultSetMapping , queryReturnType ));
247
252
253
+ if (entityGraph != null ) {
254
+ builder .add (applyEntityGraph (entityGraph , queryVariableName ));
255
+ }
256
+
248
257
if (queryHints .isPresent ()) {
249
258
builder .add (applyHints (queryVariableName , queryHints ));
250
259
builder .add ("\n " );
@@ -363,6 +372,43 @@ private Object getParameter(ParameterBinding.ParameterOrigin origin) {
363
372
throw new UnsupportedOperationException ("Not supported yet" );
364
373
}
365
374
375
+ private CodeBlock applyEntityGraph (AotEntityGraph entityGraph , String queryVariableName ) {
376
+
377
+ CodeBlock .Builder builder = CodeBlock .builder ();
378
+
379
+ if (StringUtils .hasText (entityGraph .name ())) {
380
+
381
+ builder .addStatement ("$T<?> entityGraph = $L.getEntityGraph($S)" , jakarta .persistence .EntityGraph .class ,
382
+ context .fieldNameOf (EntityManager .class ), entityGraph .name ());
383
+ } else {
384
+
385
+ builder .addStatement ("$T<$T> entityGraph = $L.createEntityGraph($T.class)" ,
386
+ jakarta .persistence .EntityGraph .class , context .getActualReturnType ().getType (),
387
+ context .fieldNameOf (EntityManager .class ), context .getActualReturnType ().getType ());
388
+
389
+ for (String attributePath : entityGraph .attributePaths ()) {
390
+
391
+ String [] pathComponents = StringUtils .delimitedListToStringArray (attributePath , "." );
392
+
393
+ StringBuilder chain = new StringBuilder ("entityGraph" );
394
+ for (int i = 0 ; i < pathComponents .length ; i ++) {
395
+
396
+ if (i < pathComponents .length - 1 ) {
397
+ chain .append (".addSubgraph($S)" );
398
+ } else {
399
+ chain .append (".addAttributeNodes($S)" );
400
+ }
401
+ }
402
+
403
+ builder .addStatement (chain .toString (), (Object []) pathComponents );
404
+ }
405
+
406
+ builder .addStatement ("$L.setHint($S, entityGraph)" , queryVariableName , entityGraph .type ().getKey ());
407
+ }
408
+
409
+ return builder .build ();
410
+ }
411
+
366
412
private CodeBlock applyHints (String queryVariableName , MergedAnnotation <QueryHints > queryHints ) {
367
413
368
414
Builder hintsBuilder = CodeBlock .builder ();
@@ -505,5 +551,4 @@ public static boolean returnsModifying(Class<?> returnType) {
505
551
506
552
}
507
553
508
-
509
554
}
0 commit comments