Как кэшировать ссылочные объекты в Morphia?

Я использую Morphia для MongoDB с Stripes Framework.

Предположим, у меня есть две сущности: Car (описывающая конкретный автомобиль, скажем, какую-то конкретную Honda Accord 1984 года) и CarType (описывающая все Honda Accord такого типа):

Самый естественный способ смоделировать это кажется:

@Entity 
class Car {
     @Id private String id; // VIN
     private Date purchaseDate;
     private Color color;
     @Reference private CarType type;

     // ..
}

@Entity
class CarType {
     @Id private String id;
     private String manufacturerId;
     private float engineDisplacement;

     // ..
}

Это работает, но неэффективно, так как CarType просматривается в БД каждый раз, когда загружается Car. Я хотел бы кэшировать типы автомобилей в памяти, так как они редко меняются. Фреймворки персистентности, такие как GORM и Hibernate, позволили бы это сделать из коробки, но я не уверен, как это сделать в Morphia (есть запрос функции, выдвинутый для этого).

Я хотел бы сохранить ссылку на CarType, так как простое сохранение String carTypeId слишком усложнило бы представления и все остальное.

Поэтому я подумал, что могу сделать что-то вроде этого:

@Entity 
class Car {
     @Id private String id; // VIN
     private Date purchaseDate;
     private Color color;
     private String typeId;

     @Transient private CarType type;
     @Transient private CarService service = new CarServiceImpl();

     public void setTypeId() {
         this.typeId = typeId;
         updateTypeReference();
     }

     @PostLoad void postLoad() {
         updateTypeReference();
     }

     private void updateTypeReference() {
         type = service.findTypeById(typeId);
     }

     // ..
}

class CarServiceImpl implements CarService {
     @CacheResult CarType findCarTypeId(String typeId) {
         datastore.get(CarType.class, typeId);
     }

     // ..
}

Который работает и делает то, что я хочу, но:

  • Похоже на взлом
  • Вместо этого я бы внедрил службу с помощью Guice, но не могу понять, как это сделать, хотя у меня есть общая инъекция зависимостей, работающая в Stripes ActionBeans.

Поэтому я хотел бы либо:

  • Узнайте, как внедрить сервисы (предпочтительно, Guice) в объекты Morphia.

or

  • Узнайте, как правильно выполнять кэширование ссылочных объектов в Morphia.

or

  • Если ничего не помогает, переключитесь на какой-либо другой подход к отображению MongoDB POJO, который поддерживает кэширование. Но мне очень нравится Морфия, так что я бы не стал.

person John M    schedule 24.12.2012    source источник


Ответы (2)


Другим распространенным подходом было бы встраивание CarType в каждый Car. Таким образом, вам нужно будет получить только один объект.

Компромиссы:

  • Вам понадобится логика обновления для всех дублированных CarType. Поскольку вы сказали, что они почти не меняются, это должно быть хорошо с точки зрения производительности.
  • Дублированные данные требуют дополнительного места на диске, и рабочий набор в оперативной памяти также увеличивается.

Вам нужно будет оценить, как это работает для ваших данных, но дублирование данных для ускорения чтения является довольно распространенным подходом...

person xeraa    schedule 25.12.2012
comment
Да, хороший момент, это еще один вариант. Для меня это не подходит, потому что, поскольку в моем приложении на самом деле это не типы автомобилей, поэтому, несмотря на то, что эти данные меняются редко (примерно раз в месяц), когда это происходит, мне приходится обновлять и повторно обрабатывать миллионы документов. - person John M; 25.12.2012
comment
Правильно, если у вас миллион дубликатов, это, вероятно, слишком неэффективно как для обновления, так и для сохранения на диск / загрузки в оперативную память. - person xeraa; 25.12.2012

Поскольку я не придумал лучшего решения, я делаю обработчик событий @PostLoad, который получает класс хранилища данных из статической переменной, а затем может искать объект, на который ссылаются.

Это похоже на взлом и требует, чтобы служба хранилища данных была потокобезопасной, но у меня это работает.

person John M    schedule 04.01.2013