Morphia List <map <string,object>&gt;&gt;返回嵌入式元素不是查找操作上的DBObject </map <string,object>

时间:2014-02-18 16:52:52

标签: java mongodb morphia

我试过这样的事情:

package org.dnylabs.kosh.data;

import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import com.google.code.morphia.Datastore;
import com.google.code.morphia.Morphia;
import com.google.code.morphia.annotations.Entity;
import com.google.code.morphia.annotations.Id;
import com.mongodb.Mongo;
import com.mongodb.MongoException;

@Entity
public class Temp {
    @Id String _id;
    List<Map<String,Object>> strings;

    public Temp(){
        strings=new LinkedList<Map<String,Object>>();
    }


    public static void main(String []args) throws UnknownHostException, MongoException{
        Mongo mongo=null;
        Morphia morphia=null;
        Datastore ds=null;
        mongo = new Mongo();
        morphia = new Morphia();
        morphia.map(Temp.class);
        ds = morphia.createDatastore(mongo, "test");
        Temp t = new Temp();
        t._id ="hi";
        Map<String, Object> m = new HashMap<String, Object>();
        m.put("Hi","1");
        m.put("Hi2",2);
        t.strings.add(m);
        ds.save(t);
        t=ds.get(t);
        ds.ensureIndexes();
    }
}

当我尝试进行findAll(9操作时,我得到了这个例外:

Caused by: java.lang.RuntimeException: org.mongodb.morphia.mapping.MappingException: Embedded element isn't a DBObject! How can it be that is a class java.lang.String
at org.mongodb.morphia.mapping. here`dedMapper.fromDBObject(EmbeddedMapper.java:172)
at org.mongodb.morphia.mapping.Mapper.readMappedField(Mapper.java:602)
at org.mongodb.morphia.mapping.Mapper.fromDb(Mapper.java:559)
at org.mongodb.morphia.mapping.EmbeddedMapper.readMapOrCollectionOrEntity(EmbeddedMapper.java:256)
at org.mongodb.morphia.mapping.EmbeddedMapper.readCollection(EmbeddedMapper.java:203)
at org.mongodb.morphia.mapping.EmbeddedMapper.fromDBObject(EmbeddedMapper.java:144)
... 16 more

经过多次尝试,我发现问题是嫁接地图。

任何人都可以帮我理解我错在哪里吗?声明似乎是正确的。

2 个答案:

答案 0 :(得分:3)

Morphia将Map视为对另一个文档的DB引用,而不是将其视为嵌入式类并视为文档。解决方案是注释Map @Embedded,但这是不可能的,因为你无法编辑Map类。

有一种方法可以通过创建另一个类并将Map定义为此类的属性并将其注释为@Embedded来实现类似于您尝试的操作。

更改Temp类:

public class Temp {
    @Id String _id;

    @Embedded // CHANGE HERE
    List<MapProxy> strings; // CHANGE HERE

    public Temp(){
        strings=new LinkedList<MapProxy>(); // CHANGE HERE
    }

    public static void main(String...args) throws UnknownHostException, MongoException{
        Mongo mongo=null;
        Morphia morphia=null;
        Datastore ds=null;
        mongo = new Mongo();
        morphia = new Morphia();
        morphia.map(Temp.class);
        ds = morphia.createDatastore(mongo, "test2");
        Temp t = new Temp();
        t._id ="hi";      
        MapProxy mp = new MapProxy(); // CHANGE HERE    
        mp.m.put("Hi","1"); // CHANGE HERE
        mp.m.put("Hi2",2); // CHANGE HERE
        t.strings.add(mp); // CHANGE HERE
        ds.save(t);
        t=ds.get(t);
        ds.ensureIndexes();
    }
}

并创建一个新类:

@Embedded
public class MapProxy {
    public Map<String,Object> m = new HashMap<String, Object>();

}

我已经标记了我所做的更改。

这产生的结构是这样的:

{
    "_id" : "hi",
    "className" : "YOUR CLASS NAME HERE",
    "strings" : 
                [ { 
                     "m" : 
                            { 
                                "Hi" : "1" , 
                                "Hi2" : 2
                            } 
                } ]
}

答案 1 :(得分:1)

所以这就是正在发生的事情。 Morphia将尝试序列化类中的任何非瞬态非静态字段。现在,如果该字段是使用@Entity注释的类型,则morphia将通过并内省事物并设置正确的映射。如果没有,在构造DBObject以交给Java驱动程序时,它会有一些默认的基本序列化程序。在这种情况下,您有一个原始类型(Object),而morphia必须对其类型和结构做出某些假设。在发现您的结构违反了这些假设后,它就会失败。这就是为什么当你像亚历克斯所展示的那样打破局面时它会起作用。这可能是以某种方式修复的,但是由于我打算从上到下重做映射代码,我预计不会尝试在当前代码中修复此问题。希望这会有所帮助。