DDD 中的 聚合根(Aggregate Root)在半自动化的 ORM 中如何持久化?

2019-04-16 10:36:02 +08:00
 lihongjie0209

我是用的是一个类似 Mybatis 的 ORM,很显然它不支持透明的持久化。聚合根在每次更新之后如何在 Repository 中识别到这些更新并持久化到数据库中。

在《实现领域驱动设计》中作者提到的两种方式

  1. 使用 ORM 如 Hibernate
  2. 使用 document store 如 MogoDB

我现在的问题是:

  1. 是不是这种半自动化 ORM+关系型数据( MYSQL )无法实现 DDD

  2. 或者实现的代价比较大(如在聚合根内部保存所有的操作记录,然后再 Repository 中根据这些记录持久化)

  3. 或者是必须使用 Event Source 这种方法来持久化(对于我来说太重了)

4606 次点击
所在节点    Java
11 条回复
ChoateYao
2019-04-16 10:48:12 +08:00
1. 可以实现
2. 这是一种思路
3. Event Source 并不是这么用的

第二种思路切分出来,使用 Domain Service 手动解决。

要不然你自己完善基础设施层,让 Repository 支持。
gsj987
2019-04-16 10:51:43 +08:00
一般使用 UnitOfWork 模式 来感知 Repository 的变化,或简单的把显式的操作放在 Application 层
lihongjie0209
2019-04-16 11:04:32 +08:00
@ChoateYao
Domain Server 不应该关心持久化的问题吧
一般都是直接调用
repo.update(ar);

我的问题是 repo.update 如何实现?
lihongjie0209
2019-04-16 11:05:52 +08:00
@gsj987

Application 更不应该关心持久化的问题

repo.update(ar);

应该是 repo 唯一暴露的更新接口,不存在显式操作
ChoateYao
2019-04-16 11:13:14 +08:00
@lihongjie0209 实际情况就是基础设施层没做好的,作出的妥协。

因为你不可能在 Application Layer 做数据拼装然后持久化,落地一个理念根据目前的情况不断做调整以达到最优情况。
ChoateYao
2019-04-16 11:15:47 +08:00
gsj987
2019-04-16 11:25:44 +08:00
@lihongjie0209 我指的是在 application 层对 repository 的显式调用,比如你说的 update。在实践中,repository 会用 IRepository 的形式作为基础设施服务,这样 application 就和具体的 orm 解除关联了。当然一般情况下,都会使用基础框架的 UoW 完成隐式更新。
lihongjie0209
2019-04-16 11:40:27 +08:00
@gsj987

类似于 Mybatis 这种半自动的 ORM, 如何实现 UOW 中的隐式更新?
gsj987
2019-04-16 13:50:28 +08:00
@lihongjie0209 这里篇文章讲了具体的实现 https://github.com/sheng-jie/UnitOfWork

因为 UoW 统一了持久化方法和事务,所以就可以用 AOP 的方式在框架层面对 UoW 进行隐式调用,如 ABP 的做法: http://www.cnblogs.com/1zhk/p/5309043.html

UoW 的作用是追踪 entity 在多个仓库间变化的依赖关系,自动帮你解决事务方法,让事务和持久化在多个聚合中保持统一,但是 IRepsoitory 的方法调用还是需要的。如果你的意思就 tracking changes 然后不调用 IRepository 更新的话,这个可能需要 orm 本身的支持。
lihongjie0209
2019-04-18 10:50:06 +08:00
@gsj987
感谢你的回复,我下去也看了 UOW, 发现一个问题

UOW 的核心是对对象的状态标记, 如果 被修改, 被删除之类的。

我找一个图, 可以帮忙说明一下吗?

https://imgur.com/HePiXYq
gsj987
2019-04-19 10:12:54 +08:00
@lihongjie0209 明白你的意思了。这个确实和 UoW 的概念没太大关系,UoW 主要作用就是事务。DDD 的设计战术之一就是一次操作只能修改一个 AR,所以需要 Domain Event 之类的东西来做关联,UoW 让各 AR 实现最终一致。

你这个例子中,确实没法在 Domain 或者 Application 层做相关的操作,因为对 Domain 他不关心持久化,对 Application 他只能看到 AR,不知道里面具体的实现。

这里你提问的半自动化 ORM,就是类似 Dapper 这样的吧?这些 micro-ORM 更多关注的是 M,而像 Hibernate 或者 EF 之类的更多的关注的是 O,也就是说前者还是一个面向数据库,效率高,透明轻快,而后者是面向对象,但是重量,不透明。在 DDD 中,领域对数据库无感知,甚至很多实践还强调聚合根里能用值对象就用值对象,所以无法在 Domain 中体现从对象关系变化映射到数据库变化的关联,这些都是由 Repository 完成的。

那么在如 EF 中,这种关联是自动实现的,因为他有 changetracker,另一方面,他还自己实现了 UoW。而 micro-ORM 没有这些,那就只能手动来做。具体的可以在 Repository 的实现中,对 AR 下的各 entity 的修改进行检查、保存。代价就是每一个特殊的检查都需要手动实现(或者如你的思路 2,自己实现一个 changetracker,如 Dapper.Contrib 就有类似的实现)。另外有些思路中,会拿 ORM 和 micro-ORM 混用,取两者的优点于一身 https://msdn.microsoft.com/zh-cn/magazine/mt703432.aspx

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/555603

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX