Skip to content

Commit b4133c0

Browse files
Reduce method signatures in Reactive-/MongoOperations and add fluent reactive api variant.
Narrow the scope of exposed methods on MongoOperations interface. The broader replace API variant has been moved to a protected method allowing users to hook into the implementation and (if needed) expose it. See: #4462 Original Pull Request: #4463
1 parent ea07e83 commit b4133c0

File tree

9 files changed

+77
-96
lines changed

9 files changed

+77
-96
lines changed

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

+1
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ public UpdateResult upsert() {
188188

189189
@Override
190190
public UpdateResult replaceFirst() {
191+
191192
if (replacement != null) {
192193
return template.replace(query, domainType, replacement,
193194
findAndReplaceOptions != null ? findAndReplaceOptions : ReplaceOptions.none(), getCollectionName());

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

+1-46
Original file line numberDiff line numberDiff line change
@@ -1783,8 +1783,6 @@ default <T> UpdateResult replace(Query query, T replacement) {
17831783
* @param replacement the replacement document. Must not be {@literal null}.
17841784
* @param collectionName the collection to query. Must not be {@literal null}.
17851785
* @return the {@link UpdateResult} which lets you access the results of the previous replacement.
1786-
* @throws org.springframework.data.mapping.MappingException if the collection name cannot be
1787-
* {@link #getCollectionName(Class) derived} from the given replacement value.
17881786
* @since 4.2
17891787
*/
17901788
default <T> UpdateResult replace(Query query, T replacement, String collectionName) {
@@ -1819,52 +1817,9 @@ default <T> UpdateResult replace(Query query, T replacement, ReplaceOptions opti
18191817
* @param replacement the replacement document. Must not be {@literal null}.
18201818
* @param options the {@link ReplaceOptions} holding additional information. Must not be {@literal null}.
18211819
* @return the {@link UpdateResult} which lets you access the results of the previous replacement.
1822-
* @throws org.springframework.data.mapping.MappingException if the collection name cannot be
1823-
* {@link #getCollectionName(Class) derived} from the given replacement value.
18241820
* @since 4.2
18251821
*/
1826-
default <T> UpdateResult replace(Query query, T replacement, ReplaceOptions options, String collectionName) {
1827-
1828-
Assert.notNull(replacement, "Replacement must not be null");
1829-
return replace(query, (Class<T>) ClassUtils.getUserClass(replacement), replacement, options, collectionName);
1830-
}
1831-
1832-
/**
1833-
* Replace a single document matching the {@link Criteria} of given {@link Query} with the {@code replacement}
1834-
* document taking {@link ReplaceOptions} into account.
1835-
*
1836-
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a document. The query may
1837-
* contain an index {@link Query#withHint(String) hint} or the {@link Query#collation(Collation) collation}
1838-
* to use. Must not be {@literal null}.
1839-
* @param entityType the type used for mapping the {@link Query} to domain type fields and deriving the collection
1840-
* @param replacement the replacement document. Must not be {@literal null}.
1841-
* @param options the {@link ReplaceOptions} holding additional information. Must not be {@literal null}.
1842-
* from. Must not be {@literal null}.
1843-
* @return the {@link UpdateResult} which lets you access the results of the previous replacement.
1844-
* @throws org.springframework.data.mapping.MappingException if the collection name cannot be
1845-
* {@link #getCollectionName(Class) derived} from the given replacement value.
1846-
* @since 4.2
1847-
*/
1848-
default <S,T> UpdateResult replace(Query query, Class<S> entityType, T replacement, ReplaceOptions options) {
1849-
return replace(query, entityType, replacement, options, getCollectionName(ClassUtils.getUserClass(entityType)));
1850-
}
1851-
1852-
/**
1853-
* Replace a single document matching the {@link Criteria} of given {@link Query} with the {@code replacement}
1854-
* document taking {@link ReplaceOptions} into account.
1855-
*
1856-
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a document. The query may
1857-
* contain an index {@link Query#withHint(String) hint} or the {@link Query#collation(Collation) collation}
1858-
* to use. Must not be {@literal null}.
1859-
* @param entityType the type used for mapping the {@link Query} to domain type fields. Must not be {@literal null}.
1860-
* @param replacement the replacement document. Must not be {@literal null}.
1861-
* @param options the {@link ReplaceOptions} holding additional information. Must not be {@literal null}.
1862-
* @param collectionName the collection to query. Must not be {@literal null}.
1863-
* @return the {@link UpdateResult} which lets you access the results of the previous replacement.
1864-
* @since 4.2
1865-
*/
1866-
<S,T> UpdateResult replace(Query query, Class<S> entityType, T replacement, ReplaceOptions options,
1867-
String collectionName);
1822+
<T> UpdateResult replace(Query query, T replacement, ReplaceOptions options, String collectionName);
18681823

18691824
/**
18701825
* Returns the underlying {@link MongoConverter}.

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

+7-1
Original file line numberDiff line numberDiff line change
@@ -2069,7 +2069,13 @@ public <T> List<T> findAllAndRemove(Query query, Class<T> entityClass, String co
20692069
}
20702070

20712071
@Override
2072-
public <S, T> UpdateResult replace(Query query, Class<S> entityType, T replacement, ReplaceOptions options,
2072+
public <T> UpdateResult replace(Query query, T replacement, ReplaceOptions options, String collectionName){
2073+
2074+
Assert.notNull(replacement, "Replacement must not be null");
2075+
return replace(query, (Class<T>) ClassUtils.getUserClass(replacement), replacement, options, collectionName);
2076+
}
2077+
2078+
protected <S, T> UpdateResult replace(Query query, Class<S> entityType, T replacement, ReplaceOptions options,
20732079
String collectionName) {
20742080

20752081
Assert.notNull(query, "Query must not be null");

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

+1-44
Original file line numberDiff line numberDiff line change
@@ -1668,8 +1668,6 @@ default <T> Mono<UpdateResult> replace(Query query, T replacement) {
16681668
* @param replacement the replacement document. Must not be {@literal null}.
16691669
* @param collectionName the collection to query. Must not be {@literal null}.
16701670
* @return the {@link UpdateResult} which lets you access the results of the previous replacement.
1671-
* @throws org.springframework.data.mapping.MappingException if the collection name cannot be
1672-
* {@link #getCollectionName(Class) derived} from the given replacement value.
16731671
* @since 4.2
16741672
*/
16751673
default <T> Mono<UpdateResult> replace(Query query, T replacement, String collectionName) {
@@ -1708,48 +1706,7 @@ default <T> Mono<UpdateResult> replace(Query query, T replacement, ReplaceOption
17081706
* {@link #getCollectionName(Class) derived} from the given replacement value.
17091707
* @since 4.2
17101708
*/
1711-
default <T> Mono<UpdateResult> replace(Query query, T replacement, ReplaceOptions options, String collectionName) {
1712-
1713-
Assert.notNull(replacement, "Replacement must not be null");
1714-
return replace(query, (Class<T>) ClassUtils.getUserClass(replacement), replacement, options, collectionName);
1715-
}
1716-
1717-
/**
1718-
* Replace a single document matching the {@link Criteria} of given {@link Query} with the {@code replacement}
1719-
* document taking {@link ReplaceOptions} into account.
1720-
*
1721-
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a document. The query may
1722-
* contain an index {@link Query#withHint(String) hint} or the {@link Query#collation(Collation) collation}
1723-
* to use. Must not be {@literal null}.
1724-
* @param entityType the type used for mapping the {@link Query} to domain type fields and deriving the collection
1725-
* @param replacement the replacement document. Must not be {@literal null}.
1726-
* @param options the {@link ReplaceOptions} holding additional information. Must not be {@literal null}.
1727-
* from. Must not be {@literal null}.
1728-
* @return the {@link UpdateResult} which lets you access the results of the previous replacement.
1729-
* @throws org.springframework.data.mapping.MappingException if the collection name cannot be
1730-
* {@link #getCollectionName(Class) derived} from the given replacement value.
1731-
* @since 4.2
1732-
*/
1733-
default <S,T> Mono<UpdateResult> replace(Query query, Class<S> entityType, T replacement, ReplaceOptions options) {
1734-
return replace(query, entityType, replacement, options, getCollectionName(ClassUtils.getUserClass(entityType)));
1735-
}
1736-
1737-
/**
1738-
* Replace a single document matching the {@link Criteria} of given {@link Query} with the {@code replacement}
1739-
* document taking {@link ReplaceOptions} into account.
1740-
*
1741-
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a document. The query may
1742-
* contain an index {@link Query#withHint(String) hint} or the {@link Query#collation(Collation) collation}
1743-
* to use. Must not be {@literal null}.
1744-
* @param entityType the type used for mapping the {@link Query} to domain type fields. Must not be {@literal null}.
1745-
* @param replacement the replacement document. Must not be {@literal null}.
1746-
* @param options the {@link ReplaceOptions} holding additional information. Must not be {@literal null}.
1747-
* @param collectionName the collection to query. Must not be {@literal null}.
1748-
* @return the {@link UpdateResult} which lets you access the results of the previous replacement.
1749-
* @since 4.2
1750-
*/
1751-
<S,T> Mono<UpdateResult> replace(Query query, Class<S> entityType, T replacement, ReplaceOptions options,
1752-
String collectionName);
1709+
<T> Mono<UpdateResult> replace(Query query, T replacement, ReplaceOptions options, String collectionName);
17531710

17541711
/**
17551712
* Map the results of an ad-hoc query on the collection for the entity class to a stream of objects of the specified

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

+7-1
Original file line numberDiff line numberDiff line change
@@ -1961,7 +1961,13 @@ public <T> Flux<T> findAllAndRemove(Query query, Class<T> entityClass, String co
19611961
}
19621962

19631963
@Override
1964-
public <S,T> Mono<UpdateResult> replace(Query query, Class<S> entityType, T replacement, ReplaceOptions options,
1964+
public <T> Mono<UpdateResult> replace(Query query, T replacement, ReplaceOptions options, String collectionName) {
1965+
1966+
Assert.notNull(replacement, "Replacement must not be null");
1967+
return replace(query, (Class<T>) ClassUtils.getUserClass(replacement), replacement, options, collectionName);
1968+
}
1969+
1970+
protected <S,T> Mono<UpdateResult> replace(Query query, Class<S> entityType, T replacement, ReplaceOptions options,
19651971
String collectionName) {
19661972

19671973
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityType);

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

+35-2
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,30 @@ interface TerminatingFindAndModify<T> {
7272
Mono<T> findAndModify();
7373
}
7474

75+
/**
76+
* Trigger <a href="https://docs.mongodb.com/manual/reference/method/db.collection.replaceOne/">replaceOne</a>
77+
* execution by calling one of the terminating methods.
78+
*
79+
* @author Christoph Strobl
80+
* @since 4.2
81+
*/
82+
interface TerminatingReplace {
83+
84+
/**
85+
* Find first and replace/upsert.
86+
*
87+
* @return never {@literal null}.
88+
*/
89+
Mono<UpdateResult> replaceFirst();
90+
}
91+
7592
/**
7693
* Compose findAndReplace execution by calling one of the terminating methods.
7794
*
7895
* @author Mark Paluch
7996
* @since 2.1
8097
*/
81-
interface TerminatingFindAndReplace<T> {
98+
interface TerminatingFindAndReplace<T> extends TerminatingReplace {
8299

83100
/**
84101
* Find, replace and return the first matching document.
@@ -202,14 +219,30 @@ interface FindAndModifyWithOptions<T> {
202219
TerminatingFindAndModify<T> withOptions(FindAndModifyOptions options);
203220
}
204221

222+
/**
223+
* @author Christoph Strobl
224+
* @since 4.2
225+
*/
226+
interface ReplaceWithOptions extends TerminatingReplace {
227+
228+
/**
229+
* Explicitly define {@link ReplaceOptions}.
230+
*
231+
* @param options must not be {@literal null}.
232+
* @return new instance of {@link FindAndReplaceOptions}.
233+
* @throws IllegalArgumentException if options is {@literal null}.
234+
*/
235+
TerminatingReplace withOptions(ReplaceOptions options);
236+
}
237+
205238
/**
206239
* Define {@link FindAndReplaceOptions}.
207240
*
208241
* @author Mark Paluch
209242
* @author Christoph Strobl
210243
* @since 2.1
211244
*/
212-
interface FindAndReplaceWithOptions<T> extends TerminatingFindAndReplace<T> {
245+
interface FindAndReplaceWithOptions<T> extends TerminatingFindAndReplace<T>, ReplaceWithOptions {
213246

214247
/**
215248
* Explicitly define {@link FindAndReplaceOptions} for the {@link Update}.

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

+23
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,17 @@ public FindAndReplaceWithProjection<T> withOptions(FindAndReplaceOptions options
165165
replacement, targetType);
166166
}
167167

168+
@Override
169+
public TerminatingReplace withOptions(ReplaceOptions options) {
170+
171+
FindAndReplaceOptions target = new FindAndReplaceOptions();
172+
if (options.isUpsert()) {
173+
target.upsert();
174+
}
175+
return new ReactiveUpdateSupport<>(template, domainType, query, update, collection, findAndModifyOptions,
176+
target, replacement, targetType);
177+
}
178+
168179
@Override
169180
public <R> FindAndReplaceWithOptions<R> as(Class<R> resultType) {
170181

@@ -174,6 +185,18 @@ public <R> FindAndReplaceWithOptions<R> as(Class<R> resultType) {
174185
findAndReplaceOptions, replacement, resultType);
175186
}
176187

188+
@Override
189+
public Mono <UpdateResult> replaceFirst() {
190+
191+
if (replacement != null) {
192+
return template.replace(query, domainType, replacement,
193+
findAndReplaceOptions != null ? findAndReplaceOptions : ReplaceOptions.none(), getCollectionName());
194+
}
195+
196+
return template.replace(query, domainType, update,
197+
findAndReplaceOptions != null ? findAndReplaceOptions : ReplaceOptions.none(), getCollectionName());
198+
}
199+
177200
private Mono<UpdateResult> doUpdate(boolean multi, boolean upsert) {
178201
return template.doUpdate(getCollectionName(), query, update, domainType, upsert, multi);
179202
}

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateReplaceTests.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ void replacesExistingDocumentWithRawDoc() {
114114
void replacesExistingDocumentWithRawDocMappingQueryAgainstDomainType() {
115115

116116
UpdateResult result = template.replace(query(where("name").is("Central Perk Cafe")), Restaurant.class,
117-
Document.parse("{ 'r-name' : 'Central Pork Cafe', 'Borough' : 'Manhattan' }"), ReplaceOptions.none());
117+
Document.parse("{ 'r-name' : 'Central Pork Cafe', 'Borough' : 'Manhattan' }"), ReplaceOptions.none(), template.getCollectionName(Restaurant.class));
118118

119119
assertThat(result.getMatchedCount()).isEqualTo(1);
120120
assertThat(result.getModifiedCount()).isEqualTo(1);

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateReplaceTests.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ void replacesExistingDocumentWithRawDoc() {
128128
void replacesExistingDocumentWithRawDocMappingQueryAgainstDomainType() {
129129

130130
Mono<UpdateResult> result = template.replace(query(where("name").is("Central Perk Cafe")), Restaurant.class,
131-
Document.parse("{ 'r-name' : 'Central Pork Cafe', 'Borough' : 'Manhattan' }"), ReplaceOptions.none());
131+
Document.parse("{ 'r-name' : 'Central Pork Cafe', 'Borough' : 'Manhattan' }"), ReplaceOptions.none(), template.getCollectionName(Restaurant.class));
132132

133133
result.as(StepVerifier::create).consumeNextWith(it -> {
134134
assertThat(it.getMatchedCount()).isEqualTo(1);

0 commit comments

Comments
 (0)