Сохранение и получение карты карт с морфием и Mongodb


Я хотел бы иметь возможность сохранять и извлекать, среди прочего, карту карт в коллекции MongoDB. Я использую Java для доступа к MongoDB через Morphia.

Пример, который я использую ниже, - это коллекция, содержащая документы, подробно описывающие владельцев различных автомобилей. В этом примере количество транспортных средств определенной марки и модели хранится на карте карт

Большинство свойств работают без каких-либо проблем, но для случая, когда a свойство-это карта карты, определенная следующим образом:

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

Объект создается (некоторые значения вставляются в карту) и сохраняется в базе данных Mongo, как и следовало ожидать:

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

Однако, когда объект извлекается с помощью кода java (запрос на консоли MongoDB работает как ожидалось)) следующим образом...

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

...код умирает ужасным образом в строке q. fetch ().

Пожалуйста, помогите :)

2 5

2 ответа:

Проблема возникает из-за того, что карта (будучи интерфейсом) не имеет конструктора по умолчанию, и хотя Morphia правильно назначала конструктор для конкретной хэш-карты на внешней карте, она не смогла решить конструктор для внутренней карты. Это привело к NullPointerException.

После долгой отладки и пробования того и другого, в конце концов я наткнулся (с помощью коллеги) на решение.

  • вместо использования свойства @ использование аннотации @встраиваемых. и
  • Объявляйте карты с помощью конкретной хэш-карты и не используйте интерфейс карты

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

Для тех из вас, кто интересуется... указание конкретного класса либо в свойстве@, либо в аннотации @Embedded никак не помогло разрешить конструктор для внутренней хэш-карты.

Поскольку мы использовали наш собственный тип данных таким образом

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

Все предыдущие рекомендации не сработали; единственное, что заставило морфию правильно прочитать данные, - это преобразовать собственный тип во множественную форму, то есть сохранить карту внутри самого собственного типа и не использовать карты внутри карт:

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

Теперь все работает нормально.