简体   繁体   English

使用 Spring 引导和 MongoDB 的域事件

[英]Domain Events with Spring Boot and MongoDB

I am working with DDD and Spring using MongoDB .我正在使用DDDSpring使用MongoDB

Now the since MongoDB is a DocumentDB and no schema validations are present, The AggregateRoot and the Document class that gets stored in the MongoDB are two different classes and the Repository translates content between those two classes while reading and writing data to database .现在,由于MongoDB是一个DocumentDB并且不存在模式验证,因此存储在 MongoDB 中的AggregateRoot和 Document Repository是这两个不同的类,并且在读取数据时这两个类和写入数据库之间转换内容database

Since the Root entity class is different from the class being stored to DB, Spring doesn't trigger the DomainEvents of the AggregateRoot .由于根实体 class 与存储到 DB 的 class 不同,因此 Spring 不会触发AggregateRootDomainEvents

  • Is there a way I can get trigger the events of the Root entity from the Repository after storing the data to the database?将数据存储到数据库后,有没有办法可以从存储库中触发根实体的事件? (maybe by an explicit invoke) (也许通过显式调用)

  • Since the MongoDB and Aggregates are a 1:1 fit.由于 MongoDB 和聚合是 1:1 的配合。 So does that mean that we generally shouldn't make a two different classes one as AggregateRoot and another the Document Class for storing aggregate roots in mongoDB?那么这是否意味着我们通常不应该创建两个不同的类,一个是AggregateRoot ,另一个是 Document Class,用于在 mongoDB 中存储聚合根? Wouldn't we have to add @Document annotation on top of our Aggregate which would leak infrastructure code in our Domain Model?难道我们不需要在我们的聚合之上添加@Document 注释,这会泄漏我们域 Model 中的基础设施代码吗?

After a while I figured out the solution, from the upvotes I believe others are facing the same problem, here is the solution:过了一会儿,我找到了解决方案,从投票中我相信其他人也面临同样的问题,这里是解决方案:

Question: Can we trigger an explicit invoke for the Domain Events?问题:我们可以触发领域事件的显式调用吗?

Answer: Yes, we can.答:是的,我们可以。 In SpringBoot we can use/ Autowire the ApplicationEventPublisher interface and then call publishEvent(event) method.SpringBoot中,我们可以使用/ Autowire ApplicationEventPublisher接口,然后调用publishEvent(event)方法。

If you're making a separate class for Db collection and Aggregate you would need to expose out your DomainEvents and a method for ClearingDomainEvents in your aggregate since the AbstractAggregateRoot<T> has these methods as protected .如果您要为 Db 收集和聚合制作单独的 class ,则需要在聚合中公开您的DomainEventsClearingDomainEvents方法,因为AbstractAggregateRoot<T>将这些方法设置为protected Below is an example of raising an event on creation:以下是在创建时引发事件的示例:

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();
    }
}

The Repository Code would look like:存储库代码如下所示:

@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();
    }
}

So does that mean that we generally shouldn't make two different classes, one as AggregateRoot and another the Document Class for storing aggregate roots in mongoDB ?那么这是否意味着我们通常不应该创建两个不同的类,一个是AggregateRoot ,另一个是 Document Class,用于在mongoDB中存储聚合根?

Answer : No, that does not mean that.回答: 不,这并不意味着。 The goal of the DDD would be to separate infrastructure from the Domain and keep the Domain agnostic of all infrastructure code. DDD的目标是将infrastructureDomain分离,并使Domain与所有基础设施代码无关。 If they both are the same then below is the impact:如果它们都相同,则影响如下:

  • Having the @Document annotation on your Aggregate Class would make you change your Domain if you're switching frameworks or swapping Mongodb with SQL .如果您要切换框架或将MongodbSQL交换,则在Aggregate Class上使用@Document注释将使您更改Domain
  • In the future in case your DB schema needs to change, you would have to either also change your aggregate class or you would have to setup the adapter classes.将来,如果您的数据库架构需要更改,您将不得不更改您的聚合 class 或者您必须设置适配器类。
  • Since the domain should only change if there is a change in business requirements and not because of infrastructure dependencies , creeping in the infrastructure annotations into the AggregateRoot would not be the best way由于域应该仅在业务需求发生变化而不是因为infrastructure dependencies项而发生变化时才发生变化,因此将infrastructure annotations潜入AggregateRoot并不是最好的方法
So when can you actually just get away with using the same class for Aggregate and Db Collection? 那么,您什么时候才能真正摆脱使用相同的 class 进行聚合和 Db 收集?

If you do want to just keep it simple and use the same class for both and not create a separate class then make sure you're sure about the below:如果您确实想保持简单并为两者使用相同的 class 而不是创建单独的 class ,请确保您确定以下内容:

  • If you're absolutely sure that you're never going to switch DBs or change frameworks.如果您绝对确定您永远不会切换数据库或更改框架。
  • You have a simple Domain Model and you don't need to store Entities of the Aggregate in a separate collection and you there is no possibility that those Entities would ever grow into their own Aggregates您有一个简单的域 Model 并且您不需要将AggregateEntities存储在单独的集合中,并且这些Entities不可能成长为自己的Aggregates

In the end it depends.最终取决于。 Feel free to drop in comments and I'll try my best to answer all of them, quite active on stack.随意发表评论,我会尽力回答所有问题,在堆栈上非常活跃。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM