Morphia List‹Map‹String,Object››› return Встроенный элемент не является DBObject при операции поиска

Я пытался сделать что-то вроде этого:

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

После многочисленных попыток я обнаружил, что проблема в привитой карте.

Может ли кто-нибудь помочь мне понять, где я ошибаюсь? Утверждение кажется правильным.


person theShadow89    schedule 18.02.2014    source источник
comment
Что ты пытаешься сделать?   -  person Sleiman Jneidi    schedule 18.02.2014
comment
Как выглядят данные в коллекциях? Можете ли вы перейти к консоли Mongo и выполнить объявление db.test.find().pretty() и опубликовать результат, чтобы мы могли увидеть, как он преобразует встроенную карту.   -  person Alex Theedom    schedule 18.02.2014


Ответы (2)


Morphia рассматривает Map как ссылку БД на другой документ, а не как встроенный класс и не рассматривает его как документ. Решением было бы аннотировать карту @Embedded, но это невозможно, поскольку вы не можете редактировать класс карты.

Существует способ добиться чего-то похожего на то, что вы пытаетесь создать, создав другой класс и определив карту как свойство этого класса и аннотировав ее как @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
                            } 
                } ]
}
person Alex Theedom    schedule 18.02.2014

Итак, вот что происходит. Morphia попытается сериализовать любое непереходное, нестатическое поле в классе. Теперь, если это поле имеет тип, аннотированный @Entity, morphia будет проходить через него, анализировать вещи и устанавливать правильные сопоставления. Если нет, то некоторые базовые сериализаторы по умолчанию будут использоваться при построении DBObject для передачи драйверу Java. В этом случае у вас есть необработанный тип (Object), и морфия должна делать определенные предположения относительно своего типа и структуры. Узнав, что ваша структура нарушает эти предположения, она сдается. Вот почему это работает, когда вы разбираете вещи, как показал Алекс. Вероятно, это тем или иным образом можно исправить, но, поскольку я планирую переделать код сопоставления сверху вниз, я не предвижу попытки исправить это в текущем коде. Надеюсь это поможет.

person evanchooly    schedule 18.02.2014