morphia MappingException:从转换器 (IdentityConverter) 设置值时出错

morphia MappingException: Error setting value from converter (IdentityConverter)

由于批量写入期间观察到的问题,我正在尝试升级我项目的 Morphia jar。

从 Morphia 0.99 到 1.1.1。更新后,我在读取实现 Iterable 的嵌入式 class 对象时遇到问题。

以下是我在阅读时看到的错误,持久记录:

java.lang.RuntimeException: org.mongodb.morphia.mapping.MappingException: Error setting value from converter (IdentityConverter)

我正在使用Mongo 2.7.3,目前无法升级。

编辑:完整堆栈跟踪:

Exception in thread "main" java.lang.RuntimeException: java.lang.RuntimeException: org.mongodb.morphia.mapping.MappingException: Error setting value from converter (IdentityConverter) for Doc.expressionTraversalTree to { "levels" : [ { "computeUnits" : [ { "computeType" : "MATH_EVAL" , "mvalExpression" : "doc['__count__'].value  +  10" }] , "level" : 0}]}
    at org.mongodb.morphia.mapping.EmbeddedMapper.fromDBObject(EmbeddedMapper.java:74)
    at org.mongodb.morphia.mapping.Mapper.readMappedField(Mapper.java:772)
    at org.mongodb.morphia.mapping.Mapper.fromDb(Mapper.java:230)
    at org.mongodb.morphia.mapping.Mapper.fromDBObject(Mapper.java:191)
    at org.mongodb.morphia.query.MorphiaIterator.convertItem(MorphiaIterator.java:134)
    at org.mongodb.morphia.query.MorphiaIterator.processItem(MorphiaIterator.java:146)
    at org.mongodb.morphia.query.MorphiaIterator.next(MorphiaIterator.java:117)
    at org.mongodb.morphia.query.QueryImpl.get(QueryImpl.java:220)
    at org.mongodb.morphia.dao.BasicDAO.findOne(BasicDAO.java:188)
    .
    .
    .
Caused by: java.lang.RuntimeException: org.mongodb.morphia.mapping.MappingException: Error setting value from converter (IdentityConverter) for Doc.expressionTraversalTree to { "levels" : [ { "computeUnits" : [ { "computeType" : "MATH_EVAL" , "mvalExpression" : "doc['__count__'].value  +  10" }] , "level" : 0}]}
    at org.mongodb.morphia.mapping.EmbeddedMapper.fromDBObject(EmbeddedMapper.java:74)
    at org.mongodb.morphia.mapping.Mapper.readMappedField(Mapper.java:768)
    at org.mongodb.morphia.mapping.Mapper.fromDb(Mapper.java:230)
    at org.mongodb.morphia.mapping.EmbeddedMapper.readMapOrCollectionOrEntity(EmbeddedMapper.java:206)
    at org.mongodb.morphia.mapping.EmbeddedMapper.readCollection(EmbeddedMapper.java:142)
    at org.mongodb.morphia.mapping.EmbeddedMapper.fromDBObject(EmbeddedMapper.java:45)
    ... 14 more
Caused by: org.mongodb.morphia.mapping.MappingException: Error setting value from converter (IdentityConverter) for Doc.expressionTraversalTree to { "levels" : [ { "computeUnits" : [ { "computeType" : "MATH_EVAL" , "mvalExpression" : "doc['__count__'].value  +  10" , "computeLevel" : 0 , "applyFilter" : false  }] , "level" : 0}]}
    at org.mongodb.morphia.converters.Converters.fromDBObject(Converters.java:128)
    at org.mongodb.morphia.mapping.EmbeddedMapper.fromDBObject(EmbeddedMapper.java:56)
    ... 19 more
Caused by: java.lang.IllegalArgumentException: Can not set ComputeExpTraversalTree field Doc.expressionTraversalTree to com.mongodb.BasicDBObject
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:164)
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:168)
    at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:81)
    at java.lang.reflect.Field.set(Field.java:741)
    at org.mongodb.morphia.mapping.MappedField.setFieldValue(MappedField.java:410)
    at org.mongodb.morphia.converters.Converters.fromDBObject(Converters.java:126)
    ... 20 more

已解决问题。作为答案发布,因为它可能对某人有所帮助。

根本原因在于对象字段 'ComputeExpTraversalTree',Morphia 无法将此对象转换为 Mongo 的 BasicDBObject。

我添加了一个自定义转换器,它将字段编码和解码到 BasicDBObject。

Converter 的片段以及如何在 Morphia 客户端上配置它。

转换器class:

public class ComputeExpressionTreeConverter extends TypeConverter implements SimpleValueConverter {

    public ComputeExpressionTreeConverter() {
        super(ComputeExpTraversalTree.class);
    }

    @Override
    public Object encode(Object value, MappedField optionalExtraInfo) {
        if (value == null) {
            return null;
        }
        DBObject dbo = null;
        String expressionTree=new Gson().toJson(
                value, ComputeExpTraversalTree.class);
        dbo=BasicDBObject.parse(expressionTree);
        return dbo;
    }

    @Override
    @SuppressWarnings("rawtypes")
    public Object decode(Class targetClass, Object fromDBObject, MappedField field) throws MappingException {
        if (fromDBObject == null) {
            return null;
        }
        DBObject dbo = (DBObject) fromDBObject;
        JsonElement jsonElement = new JsonParser().parse(dbo.toString());
        ComputeExpTraversalTree expTraversalTree = new Gson().fromJson(
                jsonElement, ComputeExpTraversalTree.class);
        return expTraversalTree;
    }

}

配置:

Morphia morphia = new Morphia();
morphia.getMapper().getConverters().addConverter(cls);

希望这会有所帮助。