[英]Domain Events with Spring Boot and MongoDB
I am working with DDD
and Spring
using MongoDB
.我正在使用DDD
和Spring
使用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 不会触发AggregateRoot
的DomainEvents
。
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:过了一会儿,我找到了解决方案,从投票中我相信其他人也面临同样的问题,这里是解决方案:
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 ,则需要在聚合中公开您的DomainEvents
和ClearingDomainEvents
方法,因为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();
}
}
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
的目标是将infrastructure
与Domain
分离,并使Domain
与所有基础设施代码无关。 If they both are the same then below is the impact:如果它们都相同,则影响如下:
@Document
annotation on your Aggregate Class
would make you change your Domain
if you're switching frameworks or swapping Mongodb
with SQL
.如果您要切换框架或将Mongodb
与SQL
交换,则在Aggregate Class
上使用@Document
注释将使您更改Domain
。infrastructure dependencies
, creeping in the infrastructure annotations
into the AggregateRoot
would not be the best way由于域应该仅在业务需求发生变化而不是因为infrastructure dependencies
项而发生变化时才发生变化,因此将infrastructure annotations
潜入AggregateRoot
并不是最好的方法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 ,请确保您确定以下内容:
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 并且您不需要将Aggregate
的Entities
存储在单独的集合中,并且这些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.