如何在没有ObjectId的情况下将Mongo与Spring Data一起使用



我有一个现有的mongo数据库,其中id(_id)被持久化为普通字符串。。这是Mongo DB:中的示例数据

{
    "_id" : "528bb0e2e4b0442f1479f1b4",
    "schoolId" : "URDLKYLFJXLWJGR193778316742298",
    "surname" : "Lewis",
    "admissionNumber" : "0347",
    "firstName" : "Martins"
}

我有一个Java对象,它的形式是:

public class Student {
@Id
private String id;
private String schoolId;
private String surname;
private String admissionNumber;
private String firstName;
}

带接收器和接收器

我还有一个仓库:

public interface StudentRepository extends MongoRepository<Student, String> {
    Student findOneBySurname(String surname);
    Student findOneById(String id);
    Student findOneBySurnameAndFirstName(String surname, String firstName);
}

当我做studentReseository.findAll()时,我能够获得数据库中所有的学生,并正确填充他们的所有字段。

当我执行studentDepository.findOne("528bb0e2e4b0442f1479f1b4")或studentDepsitory.findOneById)"528bb0 e2e4b044f1479f1b 4")时,它返回空

当我调试mongo查询时,我可以看到它正在调用:

2015-11-19 16:06:32.327 DEBUG 87081 --- [           main] o.s.data.mongodb.core.MongoTemplate      : findOne using query: { "id" : "528bb0e2e4b0442f1479f1b4"} fields: null for class: class com.ad.josh.domain.Student in collection: Student
    2015-11-19 16:06:32.331 DEBUG 87081 --- [           main] o.s.data.mongodb.core.MongoDbUtils       : Getting Mongo Database name=[joshdb]
    2015-11-19 16:06:32.333 DEBUG 87081 --- [           main] o.s.data.mongodb.core.MongoTemplate      : findOne using query: { "_id" : { "$oid" : "528bb0e2e4b0442f1479f1b4"}} in db.collection: josh.Student

通常,我可以看到它仍然使用对象Id而不是纯字符串进行查询。

我看到了以下建议:

创建一个抛出RuntimeException 的转换器

但这并不奏效;它只是抛出一个RuntimeException。

任何关于如何使用SpringData访问Mongo数据库的建议都将不胜感激,在Mongo数据库中,Id已经定义为String(在现有数据库中)。

我认为这里的问题是一个错误的"_id"格式,这就是为什么Mongo无法识别任何具有这样id的对象。它应该看起来像ObjectId("528bb0e2e4b0442f1479f1b4"),而不是纯字符串类型。

        {
            "_id" : ObjectId("528bb0e2e4b0442f1479f1b4"),
            "schoolId" : "URDLKYLFJXLWJGR193778316742298",
            "surname" : "Lewis",
            "admissionNumber" : "0347",
            "firstName" : "Martins"
        }

因此,如果您已将带有现有数据的.json导入mongo,则需要更改id:

"_id": {$oid:"528bb0e2e4b0442f1479f1b4"},

并且应该将其转换为正确的格式。

希望它能帮助到别人。

每个存储库可以使用不同的MongoTemplate,如下所述:使用Spring Data Mongo配置多个MongoDB存储库在不希望从String转换为ObjectId的存储库中,您必须使用缺少ObjectIdToStringConverter 的mongoTemplate

有一个转换器,它可以为您开箱即用地进行转换,如果您想保持String id的原样,而不将其转换为ObjectId,则必须覆盖MappingMongoConverter类中的convertId方法,我在这里举了一个例子:

/*
* 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);
    }
}

一个可行的解决方法是为ObjectId创建自己的转换器。

您可以通过提供MappingMongoConverter 类型的@Bean来自定义mongo映射程序

@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;
    }
}

最新更新