Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@
* @author Michael Krog
* @author Jakub Zurawa
* @author Florian Lüdiger
* @author Sujay HK
*/
public class MongoTemplate implements MongoOperations, ApplicationContextAware, IndexOperationsProvider,
SearchIndexOperationsProvider, ReadPreferenceAware {
Expand Down Expand Up @@ -2184,7 +2185,7 @@ public <T> UpdateResult replace(Query query, T replacement, ReplaceOptions optio
}

protected <S, T> UpdateResult replace(Query query, Class<S> entityType, T replacement, ReplaceOptions options,
String collectionName) {
String collectionName) {

Assert.notNull(query, "Query must not be null");
Assert.notNull(replacement, "Replacement must not be null");
Expand All @@ -2195,10 +2196,10 @@ protected <S, T> UpdateResult replace(Query query, Class<S> entityType, T replac
Assert.isTrue(query.getLimit() <= 1, "Query must not define a limit other than 1 ore none");
Assert.isTrue(query.getSkip() <= 0, "Query must not define skip");

replacement = maybeCallBeforeConvert(replacement, collectionName);
UpdateContext updateContext = queryOperations.replaceSingleContext(query,
operations.forEntity(replacement).toMappedDocument(this.mongoConverter), options.isUpsert());

replacement = maybeCallBeforeConvert(replacement, collectionName);
Document mappedReplacement = updateContext.getMappedUpdate(mappingContext.getPersistentEntity(entityType));
maybeEmitEvent(new BeforeSaveEvent<>(replacement, mappedReplacement, collectionName));
replacement = maybeCallBeforeSave(replacement, mappedReplacement, collectionName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@
* @author Yadhukrishna S Pai
* @author Florian Lüdiger
* @author Kyuhong Han
* @author Sujay HK
* @since 2.0
*/
public class ReactiveMongoTemplate implements ReactiveMongoOperations, ApplicationContextAware {
Expand Down Expand Up @@ -2095,25 +2096,29 @@ public <T> Mono<UpdateResult> replace(Query query, T replacement, ReplaceOptions
}

protected <S, T> Mono<UpdateResult> replace(Query query, Class<S> entityType, T replacement, ReplaceOptions options,
String collectionName) {
String collectionName) {

MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityType);
UpdateContext updateContext = queryOperations.replaceSingleContext(query,
operations.forEntity(replacement).toMappedDocument(this.mongoConverter), options.isUpsert());

return createMono(collectionName, collection -> {
return maybeCallBeforeConvert(replacement, collectionName).flatMap(converted -> {

UpdateContext updateContext = queryOperations.replaceSingleContext(query,
operations.forEntity(converted).toMappedDocument(this.mongoConverter), options.isUpsert());

Document mappedUpdate = updateContext.getMappedUpdate(entity);
return createMono(collectionName, collection -> {

MongoAction action = new MongoAction(writeConcern, MongoActionOperation.REPLACE, collectionName, entityType,
mappedUpdate, updateContext.getQueryObject());
Document mappedUpdate = updateContext.getMappedUpdate(entity);

MongoCollection<Document> collectionToUse = createCollectionPreparer(query, action).prepare(collection);
MongoAction action = new MongoAction(writeConcern, MongoActionOperation.REPLACE, collectionName, entityType,
mappedUpdate, updateContext.getQueryObject());

return collectionToUse.replaceOne(updateContext.getMappedQuery(entity), mappedUpdate,
updateContext.getReplaceOptions(entity, it -> {
it.upsert(options.isUpsert());
}));
MongoCollection<Document> collectionToUse = createCollectionPreparer(query, action).prepare(collection);

return collectionToUse.replaceOne(updateContext.getMappedQuery(entity), mappedUpdate,
updateContext.getReplaceOptions(entity, it -> {
it.upsert(options.isUpsert());
}));
});
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.mapping.MappingException;
import org.springframework.data.mapping.callback.EntityCallbacks;
import org.springframework.data.mapping.context.PersistentEntities;
import org.springframework.data.mongodb.InvalidMongoDbApiUsageException;
import org.springframework.data.mongodb.MongoDatabaseFactory;
Expand All @@ -95,8 +96,10 @@
import org.springframework.data.mongodb.core.mapping.Field;
import org.springframework.data.mongodb.core.mapping.FieldName.Type;
import org.springframework.data.mongodb.core.mapping.MongoId;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener;
import org.springframework.data.mongodb.core.mapping.event.AfterSaveEvent;
import org.springframework.data.mongodb.core.mapping.event.BeforeConvertCallback;
import org.springframework.data.mongodb.core.mapping.event.BeforeConvertEvent;
import org.springframework.data.mongodb.core.mapping.event.BeforeSaveEvent;
import org.springframework.data.mongodb.core.query.BasicQuery;
Expand Down Expand Up @@ -144,6 +147,7 @@
* @author duozhilin
* @author Jakub Zurawa
* @author Florian Lüdiger
* @author Sujay HK
*/
public class MongoTemplateTests {

Expand Down Expand Up @@ -4099,6 +4103,29 @@ void readsMapWithDotInKey() {
assertThat(loaded.mapValue).isEqualTo(sourceMap);
}

@Test // GH-5166
void beforeConvertCallbackIsAppliedOnReplace() {

PersonWithConvertedName person = new PersonWithConvertedName("sujay");
template.insert(person);

// Register a BeforeConvertCallback that uppercases the name
template.setEntityCallbacks(EntityCallbacks.create(
(BeforeConvertCallback<PersonWithConvertedName>) (entity, collection) -> {
entity.name = entity.name.toUpperCase();
return entity;
}
));

PersonWithConvertedName replacement = new PersonWithConvertedName("sujay");
replacement.id = person.id;

template.replace(query(where("id").is(person.id)), replacement);

PersonWithConvertedName found = template.findById(person.id, PersonWithConvertedName.class);
assertThat(found.name).isEqualTo("SUJAY"); // will FAIL before the fix
}

private AtomicReference<ImmutableVersioned> createAfterSaveReference() {

AtomicReference<ImmutableVersioned> saved = new AtomicReference<>();
Expand All @@ -4113,6 +4140,17 @@ public void onAfterSave(AfterSaveEvent<ImmutableVersioned> event) {
return saved;
}

@org.springframework.data.mongodb.core.mapping.Document
static class PersonWithConvertedName {

@Id String id;
String name;

PersonWithConvertedName(String name) {
this.name = name;
}
}

static class TypeWithNumbers {

@Id String id;
Expand Down Expand Up @@ -4813,6 +4851,7 @@ public void onBeforeConvert(BeforeConvertEvent<PersonWithIdPropertyOfTypeUUID> e

person.setId(UUID.randomUUID());
}

}

public static class Message {
Expand Down Expand Up @@ -5097,4 +5136,5 @@ public int hashCode() {
return Objects.hash(id, value, mapValue);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@
import org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener;
import org.springframework.data.mongodb.core.mapping.event.AfterSaveEvent;
import org.springframework.data.mongodb.core.mapping.event.BeforeConvertEvent;
import org.springframework.data.mongodb.core.mapping.event.ReactiveBeforeConvertCallback;
import org.springframework.data.mapping.callback.ReactiveEntityCallbacks;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.NearQuery;
import org.springframework.data.mongodb.core.query.Query;
Expand All @@ -89,6 +91,7 @@
*
* @author Mark Paluch
* @author Christoph Strobl
* @author Sujay HK
*/
public class ReactiveMongoTemplateTests {

Expand Down Expand Up @@ -2101,6 +2104,28 @@ public void doesNotFailOnInsertForEntityWithNonAutogeneratableId3() {
template.save(source).as(StepVerifier::create).expectNextCount(1).verifyComplete();
}

@Test // GH-5166
void beforeConvertCallbackIsAppliedOnReplace() {

PersonWithConvertedName person = new PersonWithConvertedName("sujay");
template.insert(person).block();

template.setEntityCallbacks(ReactiveEntityCallbacks.create(
(ReactiveBeforeConvertCallback<PersonWithConvertedName>) (entity, collection) -> {
entity.name = entity.name.toUpperCase();
return Mono.just(entity);
}
));

PersonWithConvertedName replacement = new PersonWithConvertedName("sujay");
replacement.id = person.id;

template.replace(query(where("id").is(person.id)), replacement).block();

PersonWithConvertedName found = template.findById(person.id, PersonWithConvertedName.class).block();
assertThat(found.name).isEqualTo("SUJAY");
}

static class NonAutogeneratableId {

@Id IdObject id;
Expand Down Expand Up @@ -2136,6 +2161,17 @@ public void setVersion(int version) {
}
}

@org.springframework.data.mongodb.core.mapping.Document
static class PersonWithConvertedName {

@Id String id;
String name;

PersonWithConvertedName(String name) {
this.name = name;
}
}

record IdObject(String value, long timestamp) {

}
Expand Down