How to use Mongo with Spring Data without ObjectId

后端 未结 4 388
小蘑菇
小蘑菇 2021-01-18 10:23

I have an existing mongo database in which ids (_id) are persisted as plain Strings.. This is sample data in Mongo DB:

{
    \"_id\" : \"528bb0e2e4b0442f1479         


        
相关标签:
4条回答
  • 2021-01-18 10:56

    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.

    0 讨论(0)
  • 2021-01-18 10:57

    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

    0 讨论(0)
  • 2021-01-18 10:57

    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);
        }
    
    }
    
    0 讨论(0)
  • 2021-01-18 11:06

    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;
        }
    
    }
    
    0 讨论(0)
提交回复
热议问题