数据库:具有 NoSQL/文档数据库 (DDD) 的存储库

标签 database orm nosql domain-driven-design repository-pattern

想从已将存储库从关系数据库迁移到 NoSQL 的任何人那里寻求任何建议吗?

我们目前正在使用 Postgres 数据库和 ORM (SQLAlchemy) 构建应用程序。但是,日后我们可能需要将应用程序迁移到当前仅支持几个 NoSQL 解决方案的环境。

考虑到这一点,我们正在遵循 Vaughn Vernon 的实现领域驱动设计中涵盖的以持久性为导向的存储库方法。这导致以下 API:

save(aggregate)
save_all(aggregates)
remove(aggregate)
get_by_...

无需详细说明,ORM 特定代码已隐藏在存储库本身中。 Session 仅用于检索或更新数据的短时间跨度,然后立即提交并关闭(在 repos 方法中)。这意味着大量合并保存,而不是最有效地使用 session 。

def save(aggregate):
try:
session.merge(aggregate)
commit
except:
rollback

def get():
try:
aggregate = session.query_by(id)
session.expunge
commit
except:
rollback
return aggregate

等等等等

优点:

  • 我们将自己限制在每个用例更新单个聚合,因此在应用程序服务中充分利用 UOW 事务控制的情况很少(性能除外)。在写入聚合时,在存储库中启用事务控制,以确保完整的聚合被持久化。
  • 没有 ORM 特定代码泄漏到存储库之外,无论如何在切换到 NoSQL 数据库时都需要重新编码。

因此,如果我们确实必须切换到 NoSQL 数据库,我们应该做最少的工作。

但是,我所读到的几乎所有内容都鼓励事务行为存在于应用程序服务层中。尽管我认为业务事务和数据库事务之间存在区别。

同样,我们正在处理性能问题,因为我们在每次调用存储库时都向 session 工厂请求一个 session 。大多数服务包含大约 3 次左右的存储库调用。

那么,对于从关系数据库迁移到 NoSQL 数据库的任何人来说,这个问题是什么?

  • 工作单元/ session 的概念在 NoSQL 世界中有意义吗?

  • 同时我们是否应该完全接受 ORM,并将 UOW/Session 从 Repository 移到 Application Service 中?

  • 如果我们这样做,如果我们最终需要迁移到 NoSQL 解决方案,重新设计应用程序服务的努力程度如何。 (在任何情况下都需要重写存储库)。

  • 最后,有人有丰富的编写与实现无关的存储库的经验吗?

附言。了解我们可以完全放弃 ORM 并同时使用纯 SQL,但我们被要求确保我们使用的是 ORM。

最佳答案

编辑:在这个答案中,我根据问题标题关注文档数据库。当然,存在具有截然不同特征的其他 NoSQL 存储(例如图形数据库、使用事件源等)。


这应该不是问题。

在文档数据库中,您的整个聚合应该是一个文档。通过这种方式,您可以获得与事务一致性所需的完全相同的保证。无论聚合中有多少实体发生变化,您仍然在存储文档。您将需要确保执行某种形式的乐观并发(通过 etag 或版本或类似方式),而不是工作单元模式,但在此之后您的事务需求得到满足。

我无法真正评论您现在是否完全接受 UoW 模式,与依赖 ORM 实现等相比。这在很大程度上取决于您的当前情况和实现细节。不过我可以说的是,您很可能不需要一次性从普通格式 (SQL) 迁移到文档。从一个简单的开始,这样您就可以了解哪些适合您,哪些不适合您。

我不知道是否存在与实现无关的存储库,但这对我来说意义不大。存储库的全部要点是封装持久性,因此您不能将其抽象化:不会分配给它们任何其他责任。此外,您不能假设存储库需要将不同的模型组合到聚合模型中:这是特定于平台的,所以它不是不可知的。

另一个最后的评论:我在你的问题中看到,对于你编写的文档,save_all(aggregates)。我不确定你指的是什么,但至少,每个聚合保存都应该包装在它自己的事务中,否则这个操作违反了聚合的事务边界特性。

关于数据库:具有 NoSQL/文档数据库 (DDD) 的存储库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51583000/

相关文章:

java - 如何通过@IndexColumn 中的数字选择集合中的第 n 个元素?

database - 如何在 Clusterpoint DB 中搜索全文匹配?

mysql - 当我打开具有 2000 万条记录的查询时,ms Access 停止工作

java - 为什么使用 Hibernate 和 Oracle 10g 方言通过 JPA 创建名为 hibernate_sequence 的序列?

php - 数据库中的复杂关系(使用 Laravel)

android - 如何在 Android 中更新 DBFlow?

mongodb - 更新非规范化的重复数据

database - CouchDB:良好的文档 ID 可降低存储要求

javascript - 我如何跟踪外部链接被点击的次数?

mysql - "Not include"约束?