Платформа воспроизведения, использующая JPA и Morphia, конфликтует при применении к одной и той же модели

У меня есть класс модели местоположения. У меня есть абстрактный класс Persister. У меня есть две реализации абстрактного класса: MySQLPersister и MongoDBPersister. Причина в том, что я могу переключаться между использованием MySQL или MongoDB, когда мне нужно. Обратите внимание, что я не использую оба одновременно. Просто для большей гибкости.

Проблема в том, что класс модели Location расширяет Model, MySQL должен будет импортировать play.db.jpa.Model. MongoDB будет импортировать play.modules.morphia.Model. Это становится проблемой, потому что каждый раз, когда я хочу переключиться, мне нужно не только изменить класс модели Location, но и изменить код в реализациях Persister из-за того, что две библиотеки имеют разные методы для модели.

Например, если я хочу перейти от использования JPA к Morphia, я должен закомментировать код в MySQLPersister. Model.find().fetch() возвращает Iterable в JPA, а Model.find().filter().asList() в Morphia даже не существует, когда я импортирую JPA.

Как мне преодолеть эту проблему? Я не хочу создавать общий класс модели и еще два идентичных класса моделей, которые импортируют каждую базу данных — это слишком много дублирования.

По сути, я нахожу дизайн play-morphia и play-jpa негибким:

JPA                             PlayMorphia
play.db.jpa.Model           >   play.modules.morphia.Model
javax.persistence.Entity    >   com.google.code.morphia.annotations.Entity

Было бы лучше, если бы и play.db.jpa.Model, и play.modules.morphia.Model были расширены из более обобщенного класса Model. Таким образом, мне не нужно менять модели, если я хочу реализовать обе базы данных.

Спасибо! Дайте мне знать, если мое объяснение непонятно.


person gruuuvy    schedule 05.06.2012    source источник


Ответы (2)


Я бы попробовал использовать еще один уровень абстракции поверх вашего слоя сохранения. Ваш абстрактный уровень должен предоставлять независимые от реализации методы для ваших потребностей в вашем приложении, а затем уровень должен делегировать вызовы фактической, зависящей от фреймворка реализации уровня сохраняемости (например, jpa.Model или Morphia.model).

Это не слишком большое дублирование, но хороший пример использования объектно-ориентированного программирования :)

person user3001    schedule 05.06.2012
comment
У меня есть абстрактный Persister с абстрактными методами для загрузки и сохранения, а также реализация добавления по умолчанию, которую также будут иметь сохранятели MySQL и MongoDB, которые расширяют этот абстрактный Persister. В этом смысле у меня есть абстрактный уровень Persister, независимый от реализации, поверх уровня, который делегирует вызов слою, зависящему от фреймворка. Но... слои, которые делегируют эти вызовы, зависят от одной и той же Модели, которую я не знаю, как исправить, не дублируя саму модель? - person gruuuvy; 05.06.2012
comment
Потому что, если я выберу маршрут дублирования моделей для удовлетворения различных баз данных, если мне придется добавить или удалить столбец, мне придется изменить их все в нескольких файлах. Другое решение, которое я могу придумать, - это использовать драйвер Java MongoDB самостоятельно, не завися от ORM для запроса объектов. - person gruuuvy; 05.06.2012

Я остановился на следующем решении:

Создайте внутренний класс Location в MySQLPersister и MongoDBPersister и используйте их для выполнения ORM и запросов к базе данных. Затем преобразуйте результаты, типизированные внутренним классом Location, в общий интерфейсный объект LocationBean. По сути, я дважды продублировал модель Location внутри внутренних классов двух Persisters.

Таким образом, если я когда-нибудь захочу переключаться между базами данных, мне просто нужно переключиться между инициализацией нового MySQLPersisteR() или нового MongoDBPersister. Если мне нужно реализовать новую базу данных, мне просто нужно снова расширить LocationPersister с собственным внутренним классом для ORM.

person gruuuvy    schedule 05.06.2012