Skip to content

Commit 41fd839

Browse files
committed
Polishing.
Add Javadoc and since tags. Refine value lookup. Include missing properties in Meta.hashCode and equals. Update documentation using boolean Meta.allowDiskUse. Add assertions to prevent accidental null propagation. See: #4667 Original pull request: #5035
1 parent 1413f43 commit 41fd839

File tree

9 files changed

+78
-28
lines changed

9 files changed

+78
-28
lines changed

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3558,7 +3558,7 @@ public FindIterable<Document> prepare(FindIterable<Document> iterable) {
35583558

35593559
Meta meta = query.getMeta();
35603560
HintFunction hintFunction = HintFunction.from(query.getHint());
3561-
if (skip <= 0 && limit <= 0 && ObjectUtils.isEmpty(sortObject) && hintFunction.isEmpty() && !meta.hasValues()
3561+
if (skip <= 0 && limit <= 0 && ObjectUtils.isEmpty(sortObject) && hintFunction.isEmpty() && meta.isEmpty()
35623562
&& query.getCollation().isEmpty()) {
35633563
return cursorToUse;
35643564
}

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3419,7 +3419,7 @@ public FindPublisher<Document> prepare(FindPublisher<Document> findPublisher) {
34193419

34203420
HintFunction hintFunction = HintFunction.from(query.getHint());
34213421
Meta meta = query.getMeta();
3422-
if (skip <= 0 && limit <= 0 && ObjectUtils.isEmpty(sortObject) && hintFunction.isEmpty() && !meta.hasValues()) {
3422+
if (skip <= 0 && limit <= 0 && ObjectUtils.isEmpty(sortObject) && hintFunction.isEmpty() && meta.isEmpty()) {
34233423
return findPublisherToUse;
34243424
}
34253425

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOptions.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,8 @@ public AggregationOptions(DiskUse allowDiskUse, boolean explain, @Nullable Docum
146146
private AggregationOptions(DiskUse diskUse, boolean explain, @Nullable Document cursor,
147147
@Nullable Collation collation, @Nullable String comment, @Nullable Object hint) {
148148

149+
Assert.notNull(diskUse, "DiskUse must not be null");
150+
149151
this.diskUse = diskUse;
150152
this.explain = explain;
151153
this.cursor = Optional.ofNullable(cursor);
@@ -442,7 +444,7 @@ static Document createCursor(int cursorBatchSize) {
442444
*/
443445
public static class Builder {
444446

445-
private @Nullable DiskUse diskUse = DiskUse.DEFAULT;
447+
private DiskUse diskUse = DiskUse.DEFAULT;
446448
private boolean explain;
447449
private @Nullable Document cursor;
448450
private @Nullable Collation collation;
@@ -470,10 +472,13 @@ public Builder allowDiskUse(boolean allowDiskUse) {
470472
*
471473
* @param diskUse use {@literal true} to allow disk use during the aggregation.
472474
* @return this.
475+
* @since 5.0
473476
*/
474477
@Contract("_ -> this")
475478
public Builder diskUse(DiskUse diskUse) {
476479

480+
Assert.notNull(diskUse, "DiskUse must not be null");
481+
477482
this.diskUse = diskUse;
478483
return this;
479484
}

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/DiskUse.java

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,31 +15,35 @@
1515
*/
1616
package org.springframework.data.mongodb.core.query;
1717

18+
import java.util.Locale;
19+
1820
import org.jspecify.annotations.Nullable;
1921
import org.springframework.util.StringUtils;
2022

2123
/**
2224
* Disk use indicates if the MongoDB server is allowed to write temporary files to disk during query/aggregation
23-
* execution. MongoDB 6.0 server (and later) default for {@literal allowDiskUseByDefault} is {@literal true} on server
24-
* side.
25+
* execution. MongoDB 6.0 server (and later) default for {@literal allowDiskUseByDefault} is {@literal true} on the
26+
* server side.
2527
*
2628
* @author Christoph Strobl
2729
* @since 5.0
30+
* @see com.mongodb.client.FindIterable#allowDiskUse(Boolean)
31+
* @see com.mongodb.reactivestreams.client.FindPublisher#allowDiskUse(Boolean)
2832
*/
2933
public enum DiskUse {
3034

3135
/**
32-
* Go with the server default value and do not specify any override.
36+
* Use the server default value and do not specify any override.
3337
*/
3438
DEFAULT,
3539

3640
/**
37-
* Override server default value and explicitly allow disk writes.
41+
* Allow disk writes.
3842
*/
3943
ALLOW,
4044

4145
/**
42-
* Override server default value and explicitly deny disk writes.
46+
* Explicitly deny disk writes.
4347
*/
4448
DENY;
4549

@@ -69,10 +73,10 @@ public static DiskUse of(@Nullable String value) {
6973
return DEFAULT;
7074
}
7175

72-
return switch (value) {
76+
return switch (value.toLowerCase(Locale.ROOT)) {
7377
case "true" -> ALLOW;
7478
case "false" -> DENY;
75-
default -> valueOf(value.toUpperCase());
79+
default -> valueOf(value.toUpperCase(Locale.ROOT));
7680
};
7781
}
7882
}

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Meta.java

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -247,15 +247,33 @@ public void setAllowDiskUse(@Nullable Boolean allowDiskUse) {
247247
setDiskUse(DiskUse.of(allowDiskUse));
248248
}
249249

250+
/**
251+
* Sets the {@link DiskUse} to control whether temporary files are allowed to be written to disk during query.
252+
*
253+
* @param diskUse must not be {@literal null}.
254+
* @since 5.0
255+
*/
250256
public void setDiskUse(DiskUse diskUse) {
257+
258+
Assert.notNull(diskUse, "DiskUse must not be null");
259+
251260
this.diskUse = diskUse;
252261
}
253262

254263
/**
255-
* @return
264+
* @return {@literal true} there is at least one values, flags, cursor batch size, or disk use set; {@literal false}
265+
* otherwise.
256266
*/
257267
public boolean hasValues() {
258-
return !this.values.isEmpty() || !this.flags.isEmpty() || this.cursorBatchSize != null || !this.diskUse.equals(DiskUse.DEFAULT);
268+
return !isEmpty();
269+
}
270+
271+
/**
272+
* @return {@literal true} if no values, flags, cursor batch size and disk use are set; {@literal false} otherwise.
273+
*/
274+
public boolean isEmpty() {
275+
return this.values.isEmpty() && this.flags.isEmpty() && this.cursorBatchSize == null
276+
&& this.diskUse.equals(DiskUse.DEFAULT);
259277
}
260278

261279
/**
@@ -303,6 +321,8 @@ public int hashCode() {
303321

304322
int hash = ObjectUtils.nullSafeHashCode(this.values);
305323
hash += ObjectUtils.nullSafeHashCode(this.flags);
324+
hash += ObjectUtils.nullSafeHashCode(this.cursorBatchSize);
325+
hash += ObjectUtils.nullSafeHashCode(this.diskUse);
306326
return hash;
307327
}
308328

@@ -320,7 +340,16 @@ public boolean equals(@Nullable Object obj) {
320340
if (!ObjectUtils.nullSafeEquals(this.values, other.values)) {
321341
return false;
322342
}
323-
return ObjectUtils.nullSafeEquals(this.flags, other.flags);
343+
344+
if (!ObjectUtils.nullSafeEquals(this.flags, other.flags)) {
345+
return false;
346+
}
347+
348+
if (!ObjectUtils.nullSafeEquals(this.cursorBatchSize, other.cursorBatchSize)) {
349+
return false;
350+
}
351+
352+
return ObjectUtils.nullSafeEquals(this.diskUse, other.diskUse);
324353
}
325354

326355
/**

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Query.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,8 @@
1515
*/
1616
package org.springframework.data.mongodb.core.query;
1717

18-
import static org.springframework.data.mongodb.core.query.SerializationUtils.serializeToJsonSafely;
19-
import static org.springframework.util.ObjectUtils.nullSafeEquals;
20-
import static org.springframework.util.ObjectUtils.nullSafeHashCode;
18+
import static org.springframework.data.mongodb.core.query.SerializationUtils.*;
19+
import static org.springframework.util.ObjectUtils.*;
2120

2221
import java.time.Duration;
2322
import java.util.ArrayList;
@@ -32,6 +31,7 @@
3231

3332
import org.bson.Document;
3433
import org.jspecify.annotations.Nullable;
34+
3535
import org.springframework.data.domain.KeysetScrollPosition;
3636
import org.springframework.data.domain.Limit;
3737
import org.springframework.data.domain.OffsetScrollPosition;
@@ -585,6 +585,17 @@ public Query allowDiskUse(boolean allowDiskUse) {
585585
return diskUse(DiskUse.of(allowDiskUse));
586586
}
587587

588+
/**
589+
* Configures writing to temporary files for aggregation stages and queries. When set to {@link DiskUse#ALLOW},
590+
* aggregation stages can write data to the {@code _tmp} subdirectory in the {@code dbPath} directory.
591+
* <p>
592+
* Note that the default value for {@literal allowDiskUseByDefault} is {@literal true} on the server side since
593+
* MongoDB 6.0.
594+
*
595+
* @param diskUse
596+
* @return this.
597+
* @since 5.0
598+
*/
588599
@Contract("_ -> this")
589600
public Query diskUse(DiskUse diskUse) {
590601

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/QueryBlocks.java

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -239,14 +239,16 @@ CodeBlock build() {
239239
if (StringUtils.hasText(source.getQuery().getFieldsString())) {
240240

241241
VariableSnippet fields = Snippet.declare(builder).variable(Document.class, context.localVariable("fields"))
242-
.of(MongoCodeBlocks.asDocument(context.getExpressionMarker(), source.getQuery().getFieldsString(), queryParameters.get()));
242+
.of(MongoCodeBlocks.asDocument(context.getExpressionMarker(), source.getQuery().getFieldsString(),
243+
queryParameters.get()));
243244
builder.addStatement("$L.setFieldsObject($L)", queryVariableName, fields.getVariableName());
244245
}
245246

246247
if (StringUtils.hasText(source.getQuery().getSortString())) {
247248

248249
VariableSnippet sort = Snippet.declare(builder).variable(Document.class, context.localVariable("sort"))
249-
.of(MongoCodeBlocks.asDocument(context.getExpressionMarker(), source.getQuery().getSortString(), getQueryParameters()));
250+
.of(MongoCodeBlocks.asDocument(context.getExpressionMarker(), source.getQuery().getSortString(),
251+
getQueryParameters()));
250252
builder.addStatement("$L.setSortObject($L)", queryVariableName, sort.getVariableName());
251253
}
252254

@@ -312,13 +314,11 @@ CodeBlock build() {
312314
} else {
313315

314316
if (getQueryParameters().isEmpty()) {
315-
builder.addStatement(
316-
"$L.collation(collationOf(evaluate($L, $S)))",
317-
queryVariableName, context.getExpressionMarker().enclosingMethod(), collationString);
317+
builder.addStatement("$L.collation(collationOf(evaluate($L, $S)))", queryVariableName,
318+
context.getExpressionMarker().enclosingMethod(), collationString);
318319
} else {
319-
builder.addStatement(
320-
"$L.collation(collationOf(evaluate($L, $S, $L)))",
321-
queryVariableName, context.getExpressionMarker().enclosingMethod(), collationString, getQueryParameters());
320+
builder.addStatement("$L.collation(collationOf(evaluate($L, $S, $L)))", queryVariableName,
321+
context.getExpressionMarker().enclosingMethod(), collationString, getQueryParameters());
322322
}
323323
}
324324
}
@@ -346,7 +346,8 @@ private CodeBlock renderExpressionToQuery() {
346346
if (getQueryParameters().isEmpty()) {
347347
builder.add("createQuery($L, $S)", context.getExpressionMarker().enclosingMethod(), source);
348348
} else {
349-
builder.add("createQuery($L, $S, $L)", context.getExpressionMarker().enclosingMethod(), source, getQueryParameters());
349+
builder.add("createQuery($L, $S, $L)", context.getExpressionMarker().enclosingMethod(), source,
350+
getQueryParameters());
350351
}
351352
return builder.build();
352353
} else {

src/main/antora/modules/ROOT/pages/mongodb/aot.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ These are typically all query methods that are not backed by an xref:repositorie
7676

7777
**Limitations**
7878

79-
* `@Meta.allowDiskUse` and `flags` are not evaluated.
79+
* `@Meta.flags` is not evaluated.
8080
* Limited `Collation` detection.
8181
* No support for in-clauses with pattern matching / case insensitivity
8282

src/main/antora/modules/ROOT/pages/mongodb/repositories/query-methods.adoc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -672,7 +672,7 @@ Use the `@Meta` annotation to set those options via `maxExecutionTimeMs`, `comme
672672
----
673673
interface PersonRepository extends CrudRepository<Person, String> {
674674
675-
@Meta(allowDiskUse = true)
675+
@Meta(allowDiskUse = "true")
676676
@Aggregation("{ $group: { _id : $lastname, names : { $addToSet : $firstname } } }")
677677
List<PersonAggregate> groupByLastnameAndFirstnames();
678678
}
@@ -684,7 +684,7 @@ Or use `@Meta` to create your own annotation as shown in the sample below.
684684
----
685685
@Retention(RetentionPolicy.RUNTIME)
686686
@Target({ ElementType.METHOD })
687-
@Meta(allowDiskUse = true)
687+
@Meta(allowDiskUse = "true")
688688
@interface AllowDiskUse { }
689689
690690
interface PersonRepository extends CrudRepository<Person, String> {

0 commit comments

Comments
 (0)