【问题标题】:Domain Events with Spring Boot and MongoDBSpring Boot 和 MongoDB 的领域事件
【发布时间】:2020-05-06 10:21:58
【问题描述】:

我正在使用MongoDBDDDSpring 合作。

现在由于MongoDBDocumentDB 并且不存在模式验证,AggregateRoot 和存储在 MongoDB 中的 Document 类是两个不同的类,Repository 在这两个类之间转换内容在向database 读写数据时。

由于 Root 实体类与存储到 DB 的类不同,Spring 不会触发 AggregateRootDomainEvents

  • 有没有办法在将数据存储到数据库后从存储库中触发根实体的事件? (可能通过显式调用)

  • 因为 MongoDB 和聚合是 1:1 匹配的。那么这是否意味着我们通常不应该创建两个不同的类,一个是AggregateRoot,另一个是用于在 mongoDB 中存储聚合根的文档类?难道我们不需要在我们的 Aggregate 上添加 @Document 注释,这会泄漏我们领域模型中的基础设施代码吗?

【问题讨论】:

    标签: java spring domain-driven-design


    【解决方案1】:

    一段时间后,我想出了解决方案,从投票中我相信其他人也面临同样的问题,这里是解决方案:

    问题:我们可以触发领域事件的显式调用吗?

    回答:是的,我们可以。在SpringBoot我们可以使用/AutowireApplicationEventPublisher接口,然后调用publishEvent(event)方法。

    如果您要为 Db 集合和聚合创建单独的类,则需要在聚合中公开 DomainEventsClearingDomainEvents 的方法,因为 AbstractAggregateRoot<T> 将这些方法作为 protected。以下是在创建时引发事件的示例:

    public class MyAggregateRootClass extends AbstractAggregateRoot<MyAggregateRootClass> 
    {
        public MyAggregateRootClass(String property1, String property2) {
    
            // set the fields here
            registerEvent(new MyAggregateRootCreated(someArgs));
        }
    
        public Collection<Object> getDomainEvents() {
            return super.domainEvents();
        }
    
        public void clearDomainEvents() {
            super.clearDomainEvents();
        }
    }
    

    存储库代码如下所示:

    @Repository
    @RequiredArgsConstructor // using lombok here, you can create a constructor if you want
    public class MyAggregateRepository {
    
        private final ApplicationEventPublisher eventPublisher;
    
        private final AggregateMongoRepository repository;
    
        public void save(MyAggregateRootClass aggToSave) {
    
            AggregateDao convertedAgg = new AggregateDao(aggToSave);
    
            repository.save(convertedAgg);
    
            // raise all the domain events
            for (Object event : aggToSave.getDomainEvents())
                eventPublisher.publishEvent(event);
    
            // clear them since all events have been raised
            aggToSave.clearDomainEvents();
        }
    }
    

    这是否意味着我们通常不应该创建两个不同的类,一个是AggregateRoot,另一个是用于在mongoDB 中存储聚合根的文档类?

    回答:不,这并不意味着。 DDD 的目标是将infrastructureDomain 分开,并使Domain 与所有基础架构代码无关。如果它们都相同,则影响如下:

    • 如果您要切换框架或将MongodbSQL 交换,在Aggregate Class 上添加@Document 注释将使您更改Domain
    • 将来,如果您的数据库架构需要更改,您必须同时更改聚合类或设置适配器类。
    • 由于只有在业务需求发生变化而不是因为infrastructure dependencies 而域才应该更改,所以将infrastructure annotations 潜入AggregateRoot 并不是最好的方法
    那么,您什么时候才能真正摆脱对 Aggregate 和 Db Collection 使用相同的类?

    如果您确实想保持简单并为两者使用相同的类而不是创建单独的类,那么请确保您确定以下内容:

    • 如果您绝对确定自己永远不会切换数据库或更改框架。
    • 你有一个简单的域模型,你不需要将Aggregate 中的Entities 存储在一个单独的集合中,你不可能那些Entities 会成长为他们自己的Aggregates

    最终取决于。随意加入 cmets,我会尽力回答所有问题,在堆栈上非常活跃。

    【讨论】:

    • 您可以使用 Monogo Template 与 Mongodb 进行交互。或者您可以使用 xml 配置。域模型和数据模型不需要使用不同的类,也不需要在域模型类上使用注释。
    • @AshwaniTiwari 你是对的,使用MongoTemplate 将允许我们不使用@Document 注释,但稍后如果数据库模式发生变化,如果我们不这样做,你也必须更改域模型' DomainModelDataModel 有两个不同的类。虽然RDBMS 可以,因为任何更改都必须使用迁移来执行,但对于Non-RDBMS,它可能会在这里和那里导致小错误,从而损害DomainModel 的完整性。
    猜你喜欢
    • 2021-07-25
    • 2019-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-06
    • 2019-09-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多