我在生产代码中使用 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);
}
...
}
然后我在实际的存储实现中使用 MongoDB Java 客户端从数据库返回我的实现实例。这是我的 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 也被实现为 MongoDB 实现的 BasicDBObject,并使用存储接口的newQuery() 生成。
还有MyDocFactory,这里没有介绍,但它基本上是一个文档工厂,它知道存储实现是什么,并相应地生成MyDoc 实例。
注意事项:
抽象没有多大意义的一件事是定义 MongoDB 存储使用的索引。我将所有ensureIndex(...) 调用都放在构造函数中,不是很通用,但是为每个集合定义索引是 MongoDB 特定的优化,所以我可以接受它。
另一个是提交是使用getLastError() 命令实现的,根据我的经验,该命令效果不佳。这对我来说不是问题,因为我几乎从不明确提交更改。