没有找到能够从类型org.bson.BsonUndefined转换的转换器

问题描述 投票:2回答:3

我有mongo驱动程序3.2.2,spring data mongodb 1.9.1.RELEASE。

收藏:

{
  "_id": "5728a1a5abdb9c352cda6432",
  "isDeleted": null,
  "name": undefined
},
{
  "_id": "5728a1a5abdb9c352cda6433",
  "isDeleted": null,
  "name": null
}

当我尝试用{"name":undefined}获取记录时,我得到以下异常。

org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type org.bson.BsonUndefined to type java.lang.String
    at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:313) ~[spring-core-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:195) ~[spring-core-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:176) ~[spring-core-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter.getPotentiallyConvertedSimpleRead(MappingMongoConverter.java:821) ~[spring-data-mongodb-1.7.1.RELEASE.jar:?]

怎么解决这个?我有多种类型需要从BsonUndefined转换,如String,Date,PhoneNumber等...

java mongodb spring-data-mongodb
3个回答
1
投票

我在我的代码上遇到了同样的问题。我不知道为什么但是由于某种原因新的mongo-java-drivers不喜欢在数据中有一个“null”值。如果您注意到当您保存对象并且值为null时,它实际上甚至不会将该字段放在文档中以开始。

我们最终得到了一个由不同的“nodejs”应用程序编写但由java读取的集合。当我们将mongo-java-driver升级到3.2版本时,特定的集合开始破坏。

我们最终不得不对该集合中的所有记录进行更新,类似于此

db.columnDefinition.update({field: null}, {$unset: {field: 1}}, {multi: true})

一旦没有包含“null”的记录被映射到对象中的bean,一切都开始正常。

我们在集合中没有一个“未定义”,但我只能猜测它也会导致问题。

我们有相同的BsonUndefined异常,即使问题与undefined无关。

org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [org.bson.BsonUndefined] to type [java.lang.String]
    at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:313) ~[spring-core-4.3.1.RELEASE.jar:4.3.1.RELEASE]
    at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:195) ~[spring-core-4.3.1.RELEASE.jar:4.3.1.RELEASE]
    at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:176) ~[spring-core-4.3.1.RELEASE.jar:4.3.1.RELEASE]

编辑:同样在我们的情况下,我们注意到它似乎并不总是一个问题。我们有其他集合,我们直接访问它们,它们有“null”字段,可以很好地读取。它似乎与从DBRef风格中提取的任何东西有关。在我的情况下,报告将DBRef添加到列,因此读取报告时会因为列中包含一个空字段而崩溃。但是报告本身的字段为空但不会中断。

这是spring-data 1.9.2,spring 4.3.1,mongo 3.2.2


0
投票

我们最近遇到了这个问题,所以我将研究结果放在这里以防其他人也遇到这个问题。

这是Spring Data MongoDB中的一个已知错误:

https://jira.spring.io/browse/DATAMONGO-1439

该链接的解决方法是添加一个显式转换器,用于从BsonUndefined转换为null。例如,使用Java 8:

@ReadingConverter
public class BsonUndefinedToNullObjectConverterFactory implements ConverterFactory<BsonUndefined, Object> {
    @Override
    public <T extends Object> Converter<BsonUndefined, T> getConverter(Class<T> targetType) {
        return o -> null;
    }
}

没有Lambda(Java 8之前版本):

@ReadingConverter
public class BsonUndefinedToNullObjectConverterFactory implements ConverterFactory<BsonUndefined, Object> {

    @Override
    public <T extends Object> Converter<BsonUndefined, T> getConverter(Class<T> targetType) {
        return new Converter<BsonUndefined, T>() {
            @Override
            public T convert(BsonUndefined source) {
                return null;
            }
        };
    }
}

0
投票

对于Java而言,该字段是否存在或具有空值并不重要,因此您也可以像上面的答案中一样替换它。但是,如果您真的想要匹配具有确切“未定义”值的字段,则只能在Mongo控制台中的JS中执行此操作。

在我的情况下,我想从对象中删除所有这些字段,因此执行正确检查和删除的函数将如下所示:

function unsetUndefined(obj) {
    return Object.keys(obj).filter((k, i) => {
        if(obj[k] === undefined) {
            delete obj[k];
            return true
        }
        return false;
    }).length > 0;
}

后来将它们组合成可执行的Mongo Shell代码,它可能是这样的:

const collectionName = "...";
const query = {...};

function unsetUndefined(obj) {
    return Object.keys(obj).some((k, i) => {
        if(obj[k] === undefined) {
            delete obj[k];
            return true;
        }
    });
}

db.getCollection(collectionName).find(query).forEach(record =>{
    const changed =  unsetUndefined(record);
    if(changed) {
        db.getCollection(collectionName).save(record);
    }
});
© www.soinside.com 2019 - 2024. All rights reserved.