You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
If you have an existing @Document entity with a unique index and you later add an @Version field to the entity class, updates to that entity via MongoRepository.save() will generate a DuplicateKeyException.
This appears to happen because MongoTemplate.doSaveVersioned() assumes that entities containing a null version field (rather than a null ID), do not currently exist and performs insert, rather than update in that case.
Ideally, this behavior would be modified to check whether an id field already exists, and if so perform an update with the version field initialized to zero if null. For now, however, it’s relatively easy to work around it by manually creating the missing version fields on existing entities directly in Mongo.
A partial stacktrace of the DuplicateKeyException being generated as described is included below. Note that we were testing against an older version of spring-data, but this is an issue on the current version as well.
org.springframework.dao.DuplicateKeyException: { "serverUsed" : “[…]” , "ok" : 1 , "n" : 0 , "err" : "insertDocument :: caused by :: 11000 E11000 duplicate key error index: […].$id dup key: { : ObjectId('[…]') }" , "code" : 11000}; nested exception is com.mongodb.MongoException$DuplicateKey: { "serverUsed" : "[…]" , "ok" : 1 , "n" : 0 , "err" : "insertDocument :: caused by :: 11000 E11000 duplicate key error index: […].$id dup key: { : ObjectId('[…]') }" , "code" : 11000}
at org.springframework.data.mongodb.core.MongoExceptionTranslator.translateExceptionIfPossible(MongoExceptionTranslator.java:55) ~[spring-data-mongodb-1.5.2.RELEASE.jar!/:na]
at org.springframework.data.mongodb.core.MongoTemplate.potentiallyConvertRuntimeException(MongoTemplate.java:1918) ~[spring-data-mongodb-1.5.2.RELEASE.jar!/:na]
at org.springframework.data.mongodb.core.MongoTemplate.execute(MongoTemplate.java:412) ~[spring-data-mongodb-1.5.2.RELEASE.jar!/:na]
at org.springframework.data.mongodb.core.MongoTemplate.insertDBObject(MongoTemplate.java:895) ~[spring-data-mongodb-1.5.2.RELEASE.jar!/:na]
at org.springframework.data.mongodb.core.MongoTemplate.doInsert(MongoTemplate.java:717) ~[spring-data-mongodb-1.5.2.RELEASE.jar!/:na]
at org.springframework.data.mongodb.core.MongoTemplate.doSaveVersioned(MongoTemplate.java:850) ~[spring-data-mongodb-1.5.2.RELEASE.jar!/:na]
at org.springframework.data.mongodb.core.MongoTemplate.save(MongoTemplate.java:837) ~[spring-data-mongodb-1.5.2.RELEASE.jar!/:na]
at org.springframework.data.mongodb.repository.support.SimpleMongoRepository.save(SimpleMongoRepository.java:72) ~[spring-data-mongodb-1.5.2.RELEASE.jar!/:na]
[…]
3 votes, 5 watchers
The text was updated successfully, but these errors were encountered:
Nathan Cantelmo opened DATAMONGO-1051 and commented
If you have an existing
@Document
entity with a unique index and you later add an@Version
field to the entity class, updates to that entity via MongoRepository.save() will generate a DuplicateKeyException.This appears to happen because MongoTemplate.doSaveVersioned() assumes that entities containing a null version field (rather than a null ID), do not currently exist and performs insert, rather than update in that case.
From MongoTemplate.java:
private <T> void doSaveVersioned(T objectToSave, MongoPersistentEntity<?> entity, String collectionName) {
[...]
// Fresh instance -> initialize version property
if (version == null) {
doInsert(collectionName, objectToSave, this.mongoConverter);
} else {
[...]
Update update = Update.fromDBObject(dbObject, ID_FIELD);
doUpdate(collectionName, query, update, objectToSave.getClass(), false, false);
}
Ideally, this behavior would be modified to check whether an id field already exists, and if so perform an update with the version field initialized to zero if null. For now, however, it’s relatively easy to work around it by manually creating the missing version fields on existing entities directly in Mongo.
A partial stacktrace of the DuplicateKeyException being generated as described is included below. Note that we were testing against an older version of spring-data, but this is an issue on the current version as well.
org.springframework.dao.DuplicateKeyException: { "serverUsed" : “[…]” , "ok" : 1 , "n" : 0 , "err" : "insertDocument :: caused by :: 11000 E11000 duplicate key error index: […].$id dup key: { : ObjectId('[…]') }" , "code" : 11000}; nested exception is com.mongodb.MongoException$DuplicateKey: { "serverUsed" : "[…]" , "ok" : 1 , "n" : 0 , "err" : "insertDocument :: caused by :: 11000 E11000 duplicate key error index: […].$id dup key: { : ObjectId('[…]') }" , "code" : 11000}
at org.springframework.data.mongodb.core.MongoExceptionTranslator.translateExceptionIfPossible(MongoExceptionTranslator.java:55) ~[spring-data-mongodb-1.5.2.RELEASE.jar!/:na]
at org.springframework.data.mongodb.core.MongoTemplate.potentiallyConvertRuntimeException(MongoTemplate.java:1918) ~[spring-data-mongodb-1.5.2.RELEASE.jar!/:na]
at org.springframework.data.mongodb.core.MongoTemplate.execute(MongoTemplate.java:412) ~[spring-data-mongodb-1.5.2.RELEASE.jar!/:na]
at org.springframework.data.mongodb.core.MongoTemplate.insertDBObject(MongoTemplate.java:895) ~[spring-data-mongodb-1.5.2.RELEASE.jar!/:na]
at org.springframework.data.mongodb.core.MongoTemplate.doInsert(MongoTemplate.java:717) ~[spring-data-mongodb-1.5.2.RELEASE.jar!/:na]
at org.springframework.data.mongodb.core.MongoTemplate.doSaveVersioned(MongoTemplate.java:850) ~[spring-data-mongodb-1.5.2.RELEASE.jar!/:na]
at org.springframework.data.mongodb.core.MongoTemplate.save(MongoTemplate.java:837) ~[spring-data-mongodb-1.5.2.RELEASE.jar!/:na]
at org.springframework.data.mongodb.repository.support.SimpleMongoRepository.save(SimpleMongoRepository.java:72) ~[spring-data-mongodb-1.5.2.RELEASE.jar!/:na]
[…]
3 votes, 5 watchers
The text was updated successfully, but these errors were encountered: