我试过这样的事情:
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
经过多次尝试,我发现问题是嫁接地图。
任何人都可以帮我理解我错在哪里吗?声明似乎是正确的。
答案 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必须对其类型和结构做出某些假设。在发现您的结构违反了这些假设后,它就会失败。这就是为什么当你像亚历克斯所展示的那样打破局面时它会起作用。这可能是以某种方式修复的,但是由于我打算从上到下重做映射代码,我预计不会尝试在当前代码中修复此问题。希望这会有所帮助。