23
23
import org .bson .Document ;
24
24
import org .jspecify .annotations .NullUnmarked ;
25
25
import org .jspecify .annotations .Nullable ;
26
+
26
27
import org .springframework .core .annotation .MergedAnnotation ;
27
28
import org .springframework .data .domain .SliceImpl ;
28
29
import org .springframework .data .domain .Sort .Order ;
40
41
import org .springframework .data .mongodb .core .query .BasicUpdate ;
41
42
import org .springframework .data .mongodb .core .query .Collation ;
42
43
import org .springframework .data .mongodb .repository .Hint ;
44
+ import org .springframework .data .mongodb .repository .Meta ;
43
45
import org .springframework .data .mongodb .repository .ReadPreference ;
44
46
import org .springframework .data .mongodb .repository .query .MongoQueryExecution .DeleteExecution ;
45
47
import org .springframework .data .mongodb .repository .query .MongoQueryExecution .PagedExecution ;
@@ -256,15 +258,13 @@ CodeBlock build() {
256
258
updateReference );
257
259
} else if (ClassUtils .isAssignable (Long .class , returnType )) {
258
260
builder .addStatement ("return $L.matching($L).apply($L).all().getModifiedCount()" ,
259
- context .localVariable ("updater" ), queryVariableName ,
260
- updateReference );
261
+ context .localVariable ("updater" ), queryVariableName , updateReference );
261
262
} else {
262
263
builder .addStatement ("$T $L = $L.matching($L).apply($L).all().getModifiedCount()" , Long .class ,
263
- context .localVariable ("modifiedCount" ), context .localVariable ("updater" ),
264
- queryVariableName , updateReference );
264
+ context .localVariable ("modifiedCount" ), context .localVariable ("updater" ), queryVariableName ,
265
+ updateReference );
265
266
builder .addStatement ("return $T.convertNumberToTargetClass($L, $T.class)" , NumberUtils .class ,
266
- context .localVariable ("modifiedCount" ),
267
- returnType );
267
+ context .localVariable ("modifiedCount" ), returnType );
268
268
}
269
269
270
270
return builder .build ();
@@ -319,11 +319,9 @@ CodeBlock build() {
319
319
Class <?> returnType = ClassUtils .resolvePrimitiveIfNecessary (queryMethod .getReturnedObjectType ());
320
320
321
321
builder .addStatement ("$T $L = $L.aggregate($L, $T.class)" , AggregationResults .class ,
322
- context .localVariable ("results" ), mongoOpsRef ,
323
- aggregationVariableName , outputType );
322
+ context .localVariable ("results" ), mongoOpsRef , aggregationVariableName , outputType );
324
323
if (!queryMethod .isCollectionQuery ()) {
325
- builder .addStatement (
326
- "return $T.<$T>firstElement(convertSimpleRawResults($T.class, $L.getMappedResults()))" ,
324
+ builder .addStatement ("return $T.<$T>firstElement(convertSimpleRawResults($T.class, $L.getMappedResults()))" ,
327
325
CollectionUtils .class , returnType , returnType , context .localVariable ("results" ));
328
326
} else {
329
327
builder .addStatement ("return convertSimpleRawResults($T.class, $L.getMappedResults())" , returnType ,
@@ -332,8 +330,7 @@ CodeBlock build() {
332
330
} else {
333
331
if (queryMethod .isSliceQuery ()) {
334
332
builder .addStatement ("$T $L = $L.aggregate($L, $T.class)" , AggregationResults .class ,
335
- context .localVariable ("results" ), mongoOpsRef ,
336
- aggregationVariableName , outputType );
333
+ context .localVariable ("results" ), mongoOpsRef , aggregationVariableName , outputType );
337
334
builder .addStatement ("boolean $L = $L.getMappedResults().size() > $L.getPageSize()" ,
338
335
context .localVariable ("hasNext" ), context .localVariable ("results" ), context .getPageableParameterName ());
339
336
builder .addStatement (
@@ -378,12 +375,16 @@ CodeBlock build() {
378
375
379
376
boolean isProjecting = context .getReturnedType ().isProjecting ();
380
377
Class <?> domainType = context .getRepositoryInformation ().getDomainType ();
381
- Object actualReturnType = isProjecting ? context .getActualReturnType ().getType ()
378
+ Object actualReturnType = queryMethod .getParameters ().hasDynamicProjection () || isProjecting
379
+ ? TypeName .get (context .getActualReturnType ().getType ())
382
380
: domainType ;
383
381
384
382
builder .add ("\n " );
385
383
386
- if (isProjecting ) {
384
+ if (queryMethod .getParameters ().hasDynamicProjection ()) {
385
+ builder .addStatement ("$T<$T> $L = $L.query($T.class).as($L)" , FindWithQuery .class , actualReturnType ,
386
+ context .localVariable ("finder" ), mongoOpsRef , domainType , context .getDynamicProjectionParameterName ());
387
+ } else if (isProjecting ) {
387
388
builder .addStatement ("$T<$T> $L = $L.query($T.class).as($T.class)" , FindWithQuery .class , actualReturnType ,
388
389
context .localVariable ("finder" ), mongoOpsRef , domainType , actualReturnType );
389
390
} else {
@@ -400,6 +401,8 @@ CodeBlock build() {
400
401
terminatingMethod = "count()" ;
401
402
} else if (query .isExists ()) {
402
403
terminatingMethod = "exists()" ;
404
+ } else if (queryMethod .isStreamQuery ()) {
405
+ terminatingMethod = "stream()" ;
403
406
} else {
404
407
terminatingMethod = Optional .class .isAssignableFrom (context .getReturnType ().toClass ()) ? "one()" : "oneValue()" ;
405
408
}
@@ -410,6 +413,12 @@ CodeBlock build() {
410
413
} else if (queryMethod .isSliceQuery ()) {
411
414
builder .addStatement ("return new $T($L, $L).execute($L)" , SlicedExecution .class ,
412
415
context .localVariable ("finder" ), context .getPageableParameterName (), query .name ());
416
+ } else if (queryMethod .isScrollQuery ()) {
417
+
418
+ String scrollPositionParameterName = context .getScrollPositionParameterName ();
419
+
420
+ builder .addStatement ("return $L.matching($L).scroll($L)" , context .localVariable ("finder" ), query .name (),
421
+ scrollPositionParameterName );
413
422
} else {
414
423
builder .addStatement ("return $L.matching($L).$L" , context .localVariable ("finder" ), query .name (),
415
424
terminatingMethod );
@@ -544,8 +553,7 @@ private CodeBlock aggregationOptions(String aggregationVariableName) {
544
553
545
554
Builder optionsBuilder = CodeBlock .builder ();
546
555
optionsBuilder .add ("$T $L = $T.builder()\n " , AggregationOptions .class ,
547
- context .localVariable ("aggregationOptions" ),
548
- AggregationOptions .class );
556
+ context .localVariable ("aggregationOptions" ), AggregationOptions .class );
549
557
optionsBuilder .indent ();
550
558
for (CodeBlock optionBlock : options ) {
551
559
optionsBuilder .add (optionBlock );
@@ -709,7 +717,27 @@ CodeBlock build() {
709
717
com .mongodb .ReadPreference .class , readPreference );
710
718
}
711
719
712
- // TODO: Meta annotation
720
+ MergedAnnotation <Meta > metaAnnotation = context .getAnnotation (Meta .class );
721
+
722
+ if (metaAnnotation .isPresent ()) {
723
+
724
+ long maxExecutionTimeMs = metaAnnotation .getLong ("maxExecutionTimeMs" );
725
+ if (maxExecutionTimeMs != -1 ) {
726
+ builder .addStatement ("$L.maxTimeMsec($L)" , queryVariableName , maxExecutionTimeMs );
727
+ }
728
+
729
+ int cursorBatchSize = metaAnnotation .getInt ("cursorBatchSize" );
730
+ if (cursorBatchSize != 0 ) {
731
+ builder .addStatement ("$L.cursorBatchSize($L)" , queryVariableName , cursorBatchSize );
732
+ }
733
+
734
+ String comment = metaAnnotation .getString ("comment" );
735
+ if (StringUtils .hasText ("comment" )) {
736
+ builder .addStatement ("$L.comment($S)" , queryVariableName , comment );
737
+ }
738
+ }
739
+
740
+ // TODO: Meta annotation: Disk usage
713
741
714
742
return builder .build ();
715
743
}
0 commit comments