首页 > 解决方案 > Spring Boot 和 MongoDB 的领域事件

问题描述

我正在使用DDDSpring使用MongoDB.

现在因为MongoDB是 aDocumentDB并且不存在模式验证,AggregateRoot存储在 MongoDB 中的 The 和 Document 类是两个不同的类,并且Repository在读取和写入数据时在这两个类之间转换内容database

由于 Root 实体类与存储到 DB 的类不同,因此 Spring 不会触发DomainEvents.AggregateRoot

标签: javaspringdomain-driven-design

解决方案


过了一会儿,我找到了解决方案,从投票中我相信其他人也面临同样的问题,这里是解决方案:

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

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

如果您正在为 Db 集合和 Aggregate 创建一个单独的类,则需要在聚合中公开您的DomainEvents和方法,ClearingDomainEvents因为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分开并保持不可知论。如果它们都相同,则影响如下:infrastructureDomainDomain

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

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

  • 如果您绝对确定您永远不会切换数据库或更改框架。
  • 您有一个简单的域模型,您不需要将其存储EntitiesAggregate单独的集合中,并且您不可能Entities将它们变成自己的Aggregates

最终取决于。随意发表评论,我会尽力回答所有问题,在堆栈上非常活跃。


推荐阅读