DATAMONGO-1639 - Make sure BeforeConvertEvent sees new version for updates.
The changes for DATAMONGO-1617 subtley changed the behavior for entity updates in terms of the version value they see for entities using optimistic locking. Previously the updates already saw the new version value, where after the fix for DATAMONGO-1617 it saw the old one. That caused BeforeConvertEvent listeners not being able to distinguish between an original insert and the first update anymore. This change is now rolled back and we introduced a test case that encodes this expectation explicitly.
This commit is contained in:
@@ -997,16 +997,12 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
doInsert(collectionName, objectToSave, this.mongoConverter);
|
||||
} else {
|
||||
|
||||
maybeEmitEvent(new BeforeConvertEvent<T>(objectToSave, collectionName));
|
||||
assertUpdateableIdIfNotSet(objectToSave);
|
||||
|
||||
// Create query for entity with the id and old version
|
||||
Object id = convertingAccessor.getProperty(idProperty);
|
||||
Query query = new Query(Criteria.where(idProperty.getName()).is(id).and(versionProperty.getName()).is(version));
|
||||
|
||||
// Bump version number
|
||||
convertingAccessor.setProperty(versionProperty, versionNumber.longValue() + 1);
|
||||
|
||||
maybeEmitEvent(new BeforeConvertEvent<T>(objectToSave, collectionName));
|
||||
assertUpdateableIdIfNotSet(objectToSave);
|
||||
|
||||
Document document = new Document();
|
||||
|
||||
this.mongoConverter.write(objectToSave, document);
|
||||
@@ -1014,6 +1010,10 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
maybeEmitEvent(new BeforeSaveEvent<T>(objectToSave, document, collectionName));
|
||||
Update update = Update.fromDocument(document, ID_FIELD);
|
||||
|
||||
// Create query for entity with the id and old version
|
||||
Object id = convertingAccessor.getProperty(idProperty);
|
||||
Query query = new Query(Criteria.where(idProperty.getName()).is(id).and(versionProperty.getName()).is(version));
|
||||
|
||||
UpdateResult result = doUpdate(collectionName, query, update, objectToSave.getClass(), false, false);
|
||||
|
||||
if (result.getModifiedCount() == 0) {
|
||||
|
||||
@@ -56,6 +56,8 @@ import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
|
||||
import org.springframework.data.mongodb.core.convert.QueryMapper;
|
||||
import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexCreator;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||
import org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener;
|
||||
import org.springframework.data.mongodb.core.mapping.event.BeforeConvertEvent;
|
||||
import org.springframework.data.mongodb.core.mapreduce.MapReduceOptions;
|
||||
import org.springframework.data.mongodb.core.query.BasicQuery;
|
||||
import org.springframework.data.mongodb.core.query.Criteria;
|
||||
@@ -75,6 +77,7 @@ import com.mongodb.client.MongoCursor;
|
||||
import com.mongodb.client.MongoDatabase;
|
||||
import com.mongodb.client.model.FindOneAndUpdateOptions;
|
||||
import com.mongodb.client.model.UpdateOptions;
|
||||
import com.mongodb.client.result.UpdateResult;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link MongoTemplate}.
|
||||
@@ -498,6 +501,36 @@ public class MongoTemplateUnitTests extends MongoOperationsUnitTests {
|
||||
verify(output, times(1)).limit(1000);
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1639
|
||||
public void beforeConvertEventForUpdateSeesNextVersion() {
|
||||
|
||||
final VersionedEntity entity = new VersionedEntity();
|
||||
entity.id = 1;
|
||||
entity.version = 0;
|
||||
|
||||
GenericApplicationContext context = new GenericApplicationContext();
|
||||
context.refresh();
|
||||
context.addApplicationListener(new AbstractMongoEventListener<VersionedEntity>() {
|
||||
|
||||
@Override
|
||||
public void onBeforeConvert(BeforeConvertEvent<VersionedEntity> event) {
|
||||
assertThat(event.getSource().version, is(1));
|
||||
}
|
||||
});
|
||||
|
||||
template.setApplicationContext(context);
|
||||
|
||||
MongoTemplate spy = Mockito.spy(template);
|
||||
|
||||
UpdateResult result = mock(UpdateResult.class);
|
||||
doReturn(1L).when(result).getModifiedCount();
|
||||
|
||||
doReturn(result).when(spy).doUpdate(anyString(), Mockito.any(Query.class), Mockito.any(Update.class),
|
||||
Mockito.any(Class.class), anyBoolean(), anyBoolean());
|
||||
|
||||
spy.save(entity);
|
||||
}
|
||||
|
||||
class AutogenerateableId {
|
||||
|
||||
@Id BigInteger id;
|
||||
|
||||
Reference in New Issue
Block a user