I have an existing mongo database in which ids (_id) are persisted as plain Strings.. This is sample data in Mongo DB:
{
\"_id\" : \"528bb0e2e4b0442f1479
I think the problem here is a wrong "_id" format and that is why Mongo cannot recognize any object with such id. It should looks like ObjectId("528bb0e2e4b0442f1479f1b4"), not plain String type.
{
"_id" : ObjectId("528bb0e2e4b0442f1479f1b4"),
"schoolId" : "URDLKYLFJXLWJGR193778316742298",
"surname" : "Lewis",
"admissionNumber" : "0347",
"firstName" : "Martins"
}
So if you have imported .json with existing data to mongo you need to change id:
"_id": {$oid:"528bb0e2e4b0442f1479f1b4"},
And it should be converted to correct format.
Hope it can help someone.
You can use different MongoTemplate
per repository as described here: Configure Multiple MongoDB repositories with Spring Data Mongo
In the repository that you don't want the conversion from String to ObjectId you have to use mongoTemplate that will lack ObjectIdToStringConverter
There's a converter behind which does this conversion out of the box for you, if you'd like to keep String id's as they're and not convert them to ObjectId you have to override the convertId method in the MappingMongoConverter
class, I've made an example here:
/*
* Note that this example I've tried on spring-data-mongodb.3.0.4.RELEASE version
* and it's not guaranteed that it will work with earlier versions
* yet the approach should be similar
*/
@Component
public class CustomMappingMongoConverter extends MappingMongoConverter {
public CustomMappingMongoConverter(MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext) {
//The constructor can differ based on the version and the dbRefResolver instance as well
super(NoOpDbRefResolver.INSTANCE, mappingContext);
}
@Override
public Object convertId(Object id, Class<?> targetType) {
if (id == null) {
return null;
} else if (ClassUtils.isAssignable(ObjectId.class, targetType) && id instanceof String && ObjectId.isValid(id.toString())) {
return id;
}
return super.convertId(id, targetType);
}
}
A workaround that could work is to create your own converter for ObjectId.
You can customize the mongo mapper by supplying a @Bean of type MappingMongoConverter
@Configuration
public class MongoConfig {
@Bean
public CustomConversions customConversions() {
List<Converter<?, ?>> converters = new ArrayList<Converter<?, ?>>();
converters.add(new MyObjectIdConverter());
return new CustomConversions(converters);
}
@Bean
public MappingMongoConverter mappingMongoConverter(MongoDbFactory factory, MongoMappingContext context, BeanFactory beanFactory) {
DbRefResolver dbRefResolver = new DefaultDbRefResolver(factory);
MappingMongoConverter mappingConverter = new MappingMongoConverter(dbRefResolver, context);
try {
mappingConverter.setCustomConversions(customConversions());
}
catch (NoSuchBeanDefinitionException ignore) {}
// Don't save _class to mongo
mappingConverter.setTypeMapper(new DefaultMongoTypeMapper(null));
return mappingConverter;
}
}