2012-09-10 4 views
5

Je voudrais pouvoir persister et récupérer, entre autres, une carte de cartes dans une collection MongoDB. J'utilise Java pour accéder à MongoDB via Morphia.Persévérer et récupérer une carte de cartes avec Morphia et Mongodb

L'exemple que j'utilise ci-dessous est une collection qui contient des documents détaillant les propriétaires de diverses voitures. Dans cet exemple, le nombre de véhicules d'une marque et d'un modèle spécifiques est stocké dans une carte de cartes

La plupart des propriétés fonctionnent sans problème, mais dans le cas où une propriété est une carte d'une carte définie de la manière suivante:

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

l'objet est créé (certaines valeurs insérées dans la carte) et a persisté à la base de données Mongo comme on pouvait s'y attendre à ce qu'il soit:

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

Toutefois, lorsque l'objet est récupéré via le code java (une requête sur le MongoDB co nsole fonctionne comme prévu)) de la manière suivante ...

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); 
} 

... le code meurt d'une façon horrible sur la ligne q.fetch().

S'il vous plaît aider :)

Répondre

7

La question provient du fait qu'une carte (étant une interface) ne dispose pas d'un constructeur par défaut, et alors que Morphia a été assignant correctement le constructeur de la HashMap en béton sur la carte extérieure il échouait à résoudre un constructeur pour la carte interne. Cela résultait de l'exception NullPointerException. Après beaucoup de débogage et d'essayer ceci et cela, j'ai fini par trébucher (avec l'aide d'un collègue) sur la solution.

  • Au lieu d'utiliser l'annotation @Property, utilisez @Embedded. et
  • Déclarez les cartes en utilisant le béton et HashMap pas utiliser l'interface de la carte

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

Pour ceux d'entre vous qui se demandent ... spécifiant la classe concrète soit dans le @property ou @Embedded l'annotation n'a rien fait pour aider à résoudre le constructeur pour le HashMap interne.

2

Depuis que nous utilisions notre propre façon datatype cette

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

toutes les recommandations précédentes ne fonctionnent pas; la seule chose faire morphia la lecture des données correctement était de transformer le OwnDataType à la forme plurielle, qui maintient une carte à l'intérieur du OwnDataType lui-même et ne pas utiliser des cartes à l'intérieur des cartes:

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

Maintenant, tout fonctionne bien.

Questions connexes