Я использую MongoDB в производственном коде с шаблоном репозитория уже более 2 лет, и могу сказать, что со временем он мне действительно помог. Абстракции хорошо подходят для тестирования (в памяти) и производства (MongoDB).
Я использую Java, и код выглядит примерно так (примерно):
public interface MyStorage {
boolean add(MyDoc doc);
boolean update(MyDoc doc);
boolean remove(String docId);
boolean commit();
MyDoc get(String docId);
MyStorageQuery newQuery();
List<MyDoc> query(MyStorageQuery q);
}
У меня есть фабрика для каждой реализации хранилища, которая создает новые экземпляры объекта MyDoc.
Я поменяю местами реализацию между MongoDb и моей собственной ручной проверкой для тестирования.
Реализация MongoDB использует класс MyDoc, который расширяет BasicDBObject следующим образом:
public interface MyDoc {
Data getData(); // let's assume this is a nested doc
void setData(Data d);
String getId();
long getTimestamp();
void setTimestamp(long time);
}
MongoDbMyDoc extends BasicDBObject implements MyDoc {
MongoDbObject() { }
void setId(String id) {
this.put("_id", id);
}
String getId() {
return super.get("_id");
}
void setData(Data d) {
dataObj = new BasicDBObject();
dataObj.put("someField",d.someField);
dataObj.put("someField2", d.someField2);
super.put("data",dataObj);
}
...
}
Затем я в реальной реализации хранилища использую Java-клиент MongoDB для возврата экземпляров моей реализации из БД. Вот конструктор для моей реализации хранилища MongoDB:
public MongoDbMyStorage(DB db, String collection) {
//DB in a mongodb object (from the client library) which was instantiated elsewhere
dbCollection = db.getCollection(collection);
dbCollection.setObjectClass(MongoDbMyDoc.class);
this.factory = new MongoDbMyDocFactory();
}
Здесь есть еще 2 интерфейса:
MyStorageQuery
, который также реализован как BasicDBObject для реализации MongoDB и сгенерирован с использованием newQuery()
интерфейса хранилища.
И MyDocFactory
, который здесь не представлен, но в основном это фабрика документов, которая знает, что такое реализация хранилища, и соответственно генерирует экземпляры MyDoc
.
Предостережения:
Одна вещь, где абстракция не имеет особого смысла, это определение индексов, используемых хранилищем MongoDB. Я поместил все свои ensureIndex(...)
вызовы в конструктор, не очень общий, но определение индексов для коллекции - это специфическая оптимизация MongoDB, поэтому я могу с этим жить.
Другое - это то, что коммит реализован с помощью команды getLastError()
, которая по моему опыту не сработала так хорошо. Для меня это не проблема, так как я почти никогда не фиксирую изменения явно.