Skip to content

Commit c385720

Browse files
DATAMONGO-2218 - Polishing.
Original Pull Request: #655
1 parent f3b7ce8 commit c385720

File tree

3 files changed

+103
-78
lines changed

3 files changed

+103
-78
lines changed

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

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,10 +140,24 @@ enum BulkMode {
140140
* Add a single replace operation to the bulk operation.
141141
*
142142
* @param query Update criteria.
143-
* @param document the document to replace, must not be {@literal null}.
143+
* @param replacement the replacement document. Must not be {@literal null}.
144144
* @return the current {@link BulkOperations} instance with the replace added, will never be {@literal null}.
145+
* @since 2.2
145146
*/
146-
BulkOperations replaceOne(Query query, Object document);
147+
default BulkOperations replaceOne(Query query, Object replacement) {
148+
return replaceOne(query, replacement, FindAndReplaceOptions.empty());
149+
}
150+
151+
/**
152+
* Add a single replace operation to the bulk operation.
153+
*
154+
* @param query Update criteria.
155+
* @param replacement the replacement document. Must not be {@literal null}.
156+
* @param options the {@link FindAndModifyOptions} holding additional information. Must not be {@literal null}.
157+
* @return the current {@link BulkOperations} instance with the replace added, will never be {@literal null}.
158+
* @since 2.2
159+
*/
160+
BulkOperations replaceOne(Query query, Object replacement, FindAndReplaceOptions options);
147161

148162
/**
149163
* Execute all bulk operations using the default write concern.

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

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -112,16 +112,7 @@ public BulkOperations insert(Object document) {
112112

113113
Assert.notNull(document, "Document must not be null!");
114114

115-
if (document instanceof Document) {
116-
117-
models.add(new InsertOneModel<>((Document) document));
118-
return this;
119-
}
120-
121-
Document sink = new Document();
122-
mongoOperations.getConverter().write(document, sink);
123-
124-
models.add(new InsertOneModel<>(sink));
115+
models.add(new InsertOneModel<>(getMappedObject(document)));
125116

126117
return this;
127118
}
@@ -258,26 +249,21 @@ public BulkOperations remove(List<Query> removes) {
258249

259250
/*
260251
* (non-Javadoc)
261-
* @see org.springframework.data.mongodb.core.BulkOperations#replaceOne(org.springframework.data.mongodb.core.query.Query, java.lang.Object)
252+
* @see org.springframework.data.mongodb.core.BulkOperations#replaceOne(org.springframework.data.mongodb.core.query.Query, java.lang.Object, org.springframework.data.mongodb.core.FindAndReplaceOptions)
262253
*/
263254
@Override
264-
public BulkOperations replaceOne(Query query, Object document) {
255+
public BulkOperations replaceOne(Query query, Object replacement, FindAndReplaceOptions options) {
265256

266257
Assert.notNull(query, "Query must not be null!");
267-
Assert.notNull(document, "Document must not be null!");
258+
Assert.notNull(replacement, "Replacement must not be null!");
259+
Assert.notNull(options, "Options must not be null!");
268260

269261
ReplaceOptions replaceOptions = new ReplaceOptions();
262+
replaceOptions.upsert(options.isUpsert());
270263
query.getCollation().map(Collation::toMongoCollation).ifPresent(replaceOptions::collation);
271-
Bson mappedQuery = getMappedQuery(query.getQueryObject());
272-
273-
if (document instanceof Document) {
274-
models.add(new ReplaceOneModel<>(mappedQuery, (Document) document, replaceOptions));
275-
return this;
276-
}
277264

278-
Document sink = new Document();
279-
mongoOperations.getConverter().write(document, sink);
280-
models.add(new ReplaceOneModel<>(mappedQuery, sink, replaceOptions));
265+
models.add(
266+
new ReplaceOneModel<>(getMappedQuery(query.getQueryObject()), getMappedObject(replacement), replaceOptions));
281267

282268
return this;
283269
}
@@ -290,7 +276,7 @@ public BulkOperations replaceOne(Query query, Object document) {
290276
public com.mongodb.bulk.BulkWriteResult execute() {
291277

292278
try {
293-
279+
294280
return mongoOperations.execute(collectionName, collection -> {
295281
return collection.bulkWrite(models.stream().map(this::mapWriteModel).collect(Collectors.toList()), bulkOptions);
296282
});
@@ -369,6 +355,17 @@ private Bson getMappedQuery(Bson query) {
369355
return bulkOperationContext.getQueryMapper().getMappedObject(query, bulkOperationContext.getEntity());
370356
}
371357

358+
private Document getMappedObject(Object source) {
359+
360+
if (source instanceof Document) {
361+
return (Document) source;
362+
}
363+
364+
Document sink = new Document();
365+
mongoOperations.getConverter().write(source, sink);
366+
return sink;
367+
}
368+
372369
private static BulkWriteOptions getBulkWriteOptions(BulkMode bulkMode) {
373370

374371
BulkWriteOptions options = new BulkWriteOptions();

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

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

18-
import static org.hamcrest.CoreMatchers.*;
19-
import static org.junit.Assert.*;
18+
import static org.assertj.core.api.Assertions.*;
2019

2120
import java.util.ArrayList;
2221
import java.util.Arrays;
2322
import java.util.List;
2423
import java.util.Optional;
2524

26-
import com.mongodb.BulkWriteException;
2725
import org.bson.Document;
28-
import org.hamcrest.core.IsInstanceOf;
2926
import org.junit.Before;
3027
import org.junit.Test;
3128
import org.junit.runner.RunWith;
@@ -95,49 +92,51 @@ public void insertOrdered() {
9592

9693
List<BaseDoc> documents = Arrays.asList(newDoc("1"), newDoc("2"));
9794

98-
assertThat(createBulkOps(BulkMode.ORDERED).insert(documents).execute().getInsertedCount(), is(2));
95+
assertThat(createBulkOps(BulkMode.ORDERED).insert(documents).execute().getInsertedCount()).isEqualTo(2);
9996
}
10097

10198
@Test // DATAMONGO-934
10299
public void insertOrderedFails() {
103100

104101
List<BaseDoc> documents = Arrays.asList(newDoc("1"), newDoc("1"), newDoc("2"));
105102

106-
try {
107-
createBulkOps(BulkMode.ORDERED).insert(documents).execute();
108-
fail();
109-
} catch (DuplicateKeyException e) {
103+
assertThatThrownBy(() -> createBulkOps(BulkMode.ORDERED).insert(documents).execute()) //
104+
.isInstanceOf(DuplicateKeyException.class) //
105+
.hasCauseInstanceOf(MongoBulkWriteException.class) //
106+
.extracting(Throwable::getCause) //
107+
.satisfies(it -> {
110108

111-
assertThat(e.getCause(), IsInstanceOf.instanceOf(MongoBulkWriteException.class));
112-
assertThat(((MongoBulkWriteException)e.getCause()).getWriteResult().getInsertedCount(), is(1)); // fails after first error
113-
assertThat(((MongoBulkWriteException)e.getCause()).getWriteErrors(), notNullValue());
114-
assertThat(((MongoBulkWriteException)e.getCause()).getWriteErrors().size(), is(1));
115-
}
109+
MongoBulkWriteException ex = (MongoBulkWriteException) it;
110+
assertThat(ex.getWriteResult().getInsertedCount()).isOne();
111+
assertThat(ex.getWriteErrors()).isNotNull();
112+
assertThat(ex.getWriteErrors().size()).isOne();
113+
});
116114
}
117115

118116
@Test // DATAMONGO-934
119117
public void insertUnOrdered() {
120118

121119
List<BaseDoc> documents = Arrays.asList(newDoc("1"), newDoc("2"));
122120

123-
assertThat(createBulkOps(BulkMode.UNORDERED).insert(documents).execute().getInsertedCount(), is(2));
121+
assertThat(createBulkOps(BulkMode.UNORDERED).insert(documents).execute().getInsertedCount()).isEqualTo(2);
124122
}
125123

126124
@Test // DATAMONGO-934
127125
public void insertUnOrderedContinuesOnError() {
128126

129127
List<BaseDoc> documents = Arrays.asList(newDoc("1"), newDoc("1"), newDoc("2"));
130128

131-
try {
132-
createBulkOps(BulkMode.UNORDERED).insert(documents).execute();
133-
fail();
134-
} catch (DuplicateKeyException e) {
129+
assertThatThrownBy(() -> createBulkOps(BulkMode.UNORDERED).insert(documents).execute()) //
130+
.isInstanceOf(DuplicateKeyException.class) //
131+
.hasCauseInstanceOf(MongoBulkWriteException.class) //
132+
.extracting(Throwable::getCause) //
133+
.satisfies(it -> {
135134

136-
assertThat(e.getCause(), IsInstanceOf.instanceOf(MongoBulkWriteException.class));
137-
assertThat(((MongoBulkWriteException)e.getCause()).getWriteResult().getInsertedCount(), is(2)); // two docs were inserted
138-
assertThat(((MongoBulkWriteException)e.getCause()).getWriteErrors(), notNullValue());
139-
assertThat(((MongoBulkWriteException)e.getCause()).getWriteErrors().size(), is(1));
140-
}
135+
MongoBulkWriteException ex = (MongoBulkWriteException) it;
136+
assertThat(ex.getWriteResult().getInsertedCount()).isEqualTo(2);
137+
assertThat(ex.getWriteErrors()).isNotNull();
138+
assertThat(ex.getWriteErrors().size()).isOne();
139+
});
141140
}
142141

143142
@Test // DATAMONGO-934
@@ -149,12 +148,12 @@ public void upsertDoesUpdate() {
149148
upsert(where("value", "value1"), set("value", "value2")).//
150149
execute();
151150

152-
assertThat(result, notNullValue());
153-
assertThat(result.getMatchedCount(), is(2));
154-
assertThat(result.getModifiedCount(), is(2));
155-
assertThat(result.getInsertedCount(), is(0));
156-
assertThat(result.getUpserts(), is(notNullValue()));
157-
assertThat(result.getUpserts().size(), is(0));
151+
assertThat(result).isNotNull();
152+
assertThat(result.getMatchedCount()).isEqualTo(2);
153+
assertThat(result.getModifiedCount()).isEqualTo(2);
154+
assertThat(result.getInsertedCount()).isZero();
155+
assertThat(result.getUpserts()).isNotNull();
156+
assertThat(result.getUpserts().size()).isZero();
158157
}
159158

160159
@Test // DATAMONGO-934
@@ -164,11 +163,11 @@ public void upsertDoesInsert() {
164163
upsert(where("_id", "1"), set("value", "v1")).//
165164
execute();
166165

167-
assertThat(result, notNullValue());
168-
assertThat(result.getMatchedCount(), is(0));
169-
assertThat(result.getModifiedCount(), is(0));
170-
assertThat(result.getUpserts(), is(notNullValue()));
171-
assertThat(result.getUpserts().size(), is(1));
166+
assertThat(result).isNotNull();
167+
assertThat(result.getMatchedCount()).isZero();
168+
assertThat(result.getModifiedCount()).isZero();
169+
assertThat(result.getUpserts()).isNotNull();
170+
assertThat(result.getUpserts().size()).isOne();
172171
}
173172

174173
@Test // DATAMONGO-934
@@ -220,10 +219,24 @@ public void replaceOneDoesReplace() {
220219
replaceOne(where("_id", "1"), rawDoc("1", "value2")).//
221220
execute();
222221

223-
assertThat(result, notNullValue());
224-
assertThat(result.getMatchedCount(), is(1));
225-
assertThat(result.getModifiedCount(), is(1));
226-
assertThat(result.getInsertedCount(), is(0));
222+
assertThat(result).isNotNull();
223+
assertThat(result.getMatchedCount()).isOne();
224+
assertThat(result.getModifiedCount()).isOne();
225+
assertThat(result.getInsertedCount()).isZero();
226+
}
227+
228+
@Test // DATAMONGO-2218
229+
public void replaceOneWithUpsert() {
230+
231+
com.mongodb.bulk.BulkWriteResult result = createBulkOps(BulkMode.ORDERED).//
232+
replaceOne(where("_id", "1"), rawDoc("1", "value2"), FindAndReplaceOptions.options().upsert()).//
233+
execute();
234+
235+
assertThat(result).isNotNull();
236+
assertThat(result.getMatchedCount()).isZero();
237+
assertThat(result.getInsertedCount()).isZero();
238+
assertThat(result.getModifiedCount()).isZero();
239+
assertThat(result.getUpserts().size()).isOne();
227240
}
228241

229242
/**
@@ -237,10 +250,10 @@ public void mixedBulkOrdered() {
237250
remove(where("value", "v2")).//
238251
execute();
239252

240-
assertThat(result, notNullValue());
241-
assertThat(result.getInsertedCount(), is(1));
242-
assertThat(result.getModifiedCount(), is(1));
243-
assertThat(result.getDeletedCount(), is(1));
253+
assertThat(result).isNotNull();
254+
assertThat(result.getInsertedCount()).isOne();
255+
assertThat(result.getModifiedCount()).isOne();
256+
assertThat(result.getDeletedCount()).isOne();
244257
}
245258

246259
/**
@@ -257,10 +270,10 @@ public void mixedBulkOrderedWithList() {
257270
com.mongodb.bulk.BulkWriteResult result = createBulkOps(BulkMode.ORDERED, BaseDoc.class).insert(inserts)
258271
.updateMulti(updates).remove(removes).execute();
259272

260-
assertThat(result, notNullValue());
261-
assertThat(result.getInsertedCount(), is(3));
262-
assertThat(result.getModifiedCount(), is(2));
263-
assertThat(result.getDeletedCount(), is(1));
273+
assertThat(result).isNotNull();
274+
assertThat(result.getInsertedCount()).isEqualTo(3);
275+
assertThat(result.getModifiedCount()).isEqualTo(2);
276+
assertThat(result.getDeletedCount()).isOne();
264277
}
265278

266279
@Test // DATAMONGO-1534
@@ -275,8 +288,8 @@ public void insertShouldConsiderInheritance() {
275288

276289
BaseDoc doc = operations.findOne(where("_id", specialDoc.id), BaseDoc.class, COLLECTION_NAME);
277290

278-
assertThat(doc, notNullValue());
279-
assertThat(doc, instanceOf(SpecialDoc.class));
291+
assertThat(doc).isNotNull();
292+
assertThat(doc).isInstanceOf(SpecialDoc.class);
280293
}
281294

282295
private void testUpdate(BulkMode mode, boolean multi, int expectedUpdates) {
@@ -292,7 +305,7 @@ private void testUpdate(BulkMode mode, boolean multi, int expectedUpdates) {
292305
int modifiedCount = multi ? bulkOps.updateMulti(updates).execute().getModifiedCount()
293306
: bulkOps.updateOne(updates).execute().getModifiedCount();
294307

295-
assertThat(modifiedCount, is(expectedUpdates));
308+
assertThat(modifiedCount).isEqualTo(expectedUpdates);
296309
}
297310

298311
private void testRemove(BulkMode mode) {
@@ -301,7 +314,7 @@ private void testRemove(BulkMode mode) {
301314

302315
List<Query> removes = Arrays.asList(where("_id", "1"), where("value", "value2"));
303316

304-
assertThat(createBulkOps(mode).remove(removes).execute().getDeletedCount(), is(3));
317+
assertThat(createBulkOps(mode).remove(removes).execute().getDeletedCount()).isEqualTo(3);
305318
}
306319

307320
private void testReplaceOne(BulkMode mode) {
@@ -314,7 +327,7 @@ private void testReplaceOne(BulkMode mode) {
314327
Document document = rawDoc("1", "value2");
315328
int modifiedCount = bulkOps.replaceOne(query, document).execute().getModifiedCount();
316329

317-
assertThat(modifiedCount, is(1));
330+
assertThat(modifiedCount).isOne();
318331
}
319332

320333
private BulkOperations createBulkOps(BulkMode mode) {
@@ -324,7 +337,8 @@ private BulkOperations createBulkOps(BulkMode mode) {
324337
private BulkOperations createBulkOps(BulkMode mode, Class<?> entityType) {
325338

326339
Optional<? extends MongoPersistentEntity<?>> entity = entityType != null
327-
? Optional.of(operations.getConverter().getMappingContext().getPersistentEntity(entityType)) : Optional.empty();
340+
? Optional.of(operations.getConverter().getMappingContext().getPersistentEntity(entityType))
341+
: Optional.empty();
328342

329343
BulkOperationContext bulkOperationContext = new BulkOperationContext(mode, entity,
330344
new QueryMapper(operations.getConverter()), new UpdateMapper(operations.getConverter()));

0 commit comments

Comments
 (0)