我有一个现有的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;
}
}