Spring Boot和MongoDB的域事件 [英] Domain Events with Spring Boot and MongoDB
问题描述
我正在使用 MongoDB
DDD 和 Spring
>。
I am working with DDD
and Spring
using MongoDB
.
现在,由于 MongoDB
是 DocumentDB
而没有存在模式验证, AggregateRoot
和存储在MongoDB中的Document类是两个不同的类,而 Repository
在读取和写入数据到数据库
的同时,在这两个类之间转换内容。
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
.
由于Root实体类与存储在数据库中的类不同,因此Spring不会触发 DomainEvents
AggregateRoot
的值。
Since the Root entity class is different from the class being stored to DB, Spring doesn't trigger the DomainEvents
of the AggregateRoot
.
-
在将数据存储到数据库之后,是否有办法从存储库中触发Root实体的事件? (也许通过显式调用)
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)
因为MongoDB和Aggregates是1:1匹配的。因此,这是否意味着我们通常不应该创建两个不同的类,一个作为 AggregateRoot
,另一个作为在MongoDB中存储聚合根的文档类?
Since the MongoDB and Aggregates are a 1:1 fit. 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? Wouldn't we have to add @Document annotation on top of our Aggregate which would leak infrastructure code in our Domain Model?
推荐答案
过了一会儿,我就找到了解决方案,我认为其他人也面临着同样的问题,下面是解决方案:
After a while I figured out the solution, from the upvotes I believe others are facing the same problem, here is the solution:
答案:是的,可以。在 SpringBoot
中,我们可以使用/ Autowire
ApplicationEventPublisher
接口和然后调用 publishEvent(event)
方法。
Answer: Yes, we can. In SpringBoot
we can use/Autowire
the ApplicationEventPublisher
interface and then call publishEvent(event)
method.
如果要为Db收集和聚合创建单独的类,则需要公开从 AbstractAggregateRoot< T> <开始,在总计中清除
DomainEvents
和 ClearingDomainEvents
的方法/ code>具有受保护
的这些方法。以下是在创建时引发事件的示例:
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
. 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();
}
}
存储库代码如下:
@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
的目标是将基础结构
与 Domain
并保持 Domain
与所有基础结构代码无关。如果它们相同,那么将产生以下影响:
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
?
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. If they both are the same then below is the impact:
- 在您的文件上具有
@Document
批注如果要切换框架或交换Mongodb <,则
聚合类
将使您更改域
。 / code>和SQL
。 - 将来,如果需要更改数据库架构,则必须
- 因为域只应在业务需求发生变化时才更改,而不是因为
而更改,所以您必须设置适配器类。
- 基础结构依赖性,将
基础结构批注
爬入AggregateRoot
并不是最好的方法
- Having the
@Document
annotation on yourAggregate Class
would make you change yourDomain
if you're switching frameworks or swappingMongodb
withSQL
. - 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.
- Since the domain should only change if there is a change in business requirements and not because of
infrastructure dependencies
, creeping in theinfrastructure annotations
into theAggregateRoot
would not be the best way
如果您只是想保持简单并为两者使用相同的类而不创建单独的类,请确保对以下内容有所了解:
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:
- 如果您绝对确定自己永远不会切换数据库或更改框架。
- 您有一个简单的域模型,不需要将
集合
的实体
存储在一个单独的集合中,并且您不会有那些实体
最终将成长为自己的聚合
- 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 theAggregate
in a separate collection and you there is no possibility that thoseEntities
would ever grow into their ownAggregates
这取决于。随意发表评论,我会尽力回答所有问题,并且在堆栈上非常活跃。
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.
这篇关于Spring Boot和MongoDB的域事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!