DDD 中的 聚合根(Aggregate Root)在半自动化的 ORM 中如何持久化? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
lihongjie0209
V2EX    Java

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

  •  
  •   lihongjie0209 2019-04-16 10:36:02 +08:00 5207 次点击
    这是一个创建于 2375 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

    我现在的问题是:

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

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

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

    11 条回复    2019-04-19 10:12:54 +08:00
    ChoateYao
        1
    ChoateYao  
       2019-04-16 10:48:12 +08:00
    1. 可以实现
    2. 这是一种思路
    3. Event Source 并不是这么用的

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

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

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

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

    repo.update(ar);

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

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

    类似于 Mybatis 这种半自动的 ORM, 如何实现 UOW 中的隐式更新?
    gsj987
        9
    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
        10
    lihongjie0209  
    OP
       2019-04-18 10:50:06 +08:00
    @gsj987
    感谢你的回复,我下去也看了 UOW, 发现一个问题

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

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

    https://imgur.com/HePiXYq
    gsj987
        11
    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
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5415 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 08:47 PVG 16:47 LAX 01:47 JFK 04:47
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86