2012-09-10 10 views
5

Me gustaría poder conservar y recuperar, entre otras cosas, un mapa de mapas en una colección MongoDB. Estoy usando Java para acceder al MongoDB a través de Morphia.Persistencia y recuperación de un mapa de mapas con Morphia y Mongodb

El ejemplo que estoy usando a continuación es una colección que contiene documentos que detallan los propietarios de varios automóviles. En este ejemplo, el número de vehículos de una marca y modelo específicos se almacena en un mapa de mapas

La mayoría de las propiedades funcionan sin problemas, pero para el caso en que una propiedad es un mapa de un mapa definido de la siguiente manera:

@Property("vehicles") 
private Map<String, Map<String, Integer> vehicles = new HashMap<String, HashMap<String, Integer>>(); 

se crea el objeto (algunos valores insertados en el mapa) y persistió a la base de datos Mongo, como es de esperar que sea:

"vehicles" : { 
    "FORD" : { 
     "FIESTA" : 1 
    }, 
    "TOYOTA" : { 
     "COROLLA" : 1,     
     "PRIUS": 1 
    }, 
    "BMW" : { 
     "SLK" : 1 
    } 
} 

Sin embargo, cuando el objeto es recuperado a través de código java (una consulta en el MongoDB co nsole funciona como se espera)) de la siguiente manera ...

Query<Owner> q = ds.find(Owner.class);  
System.out.println(q.countAll()); 
Iterable<Owner> i = q.fetch(); 
for (Owner o : i) { 
    System.out.println(o); 
} 

... el código muere de una manera horrible en la línea q.fetch().

Por favor ayuda :)

Respuesta

7

El problema se deriva del hecho de que un mapa (siendo una interfaz) no tiene un constructor por defecto, y mientras Morphia estaba asignando correctamente el constructor de la HashMap concreta en el Mapa externa se no pudo resolver un constructor para el Mapa interno. Esto estaba dando como resultado la NullPointerException.

Después de mucha depuración y de probar esto y lo otro, finalmente tropecé (con la ayuda de un colega) en la solución.

  • En lugar de utilizar la anotación @Property use @Embedded. y
  • Declarar los mapas mediante el HashMap concreto y no utilizar la interfaz del mapa

    @Embedded("vehicles") 
    private HashMap<String, HashMap<String, Integer>> vehicles = new HashMap<String, HashMap<String, Integer>>(); 
    

Para aquellos de ustedes que se preguntan ... especificando la clase concreta, ya sea en el @Property o @Embedded la anotación no hizo nada para ayudar a resolver el constructor para el HashMap interno.

2

ya que estábamos usando nuestro propio tipo de datos de esta manera

private HashMap<String, HashMap<String, OwnDataType>> vehicles = new HashMap<String, HashMap<String, OwnDataType>>(); 

todas las recomendaciones anteriores no funcionaron; lo único por lo lea correctamente los datos morfina era transformar la OwnDataType de forma plural, que es mantener un mapa dentro de la propia OwnDataType y no utilizar los mapas en el interior de los mapas:

private HashMap<String, OwnDataTypes> vehicles = new HashMap<String, OwnDataTypes>(); 

bien ahora todo está funcionando.

Cuestiones relacionadas