java - Spring Boot 和 MongoDB 的领域事件
问题描述
我正在使用DDD
和Spring
使用MongoDB
.
现在因为MongoDB
是 aDocumentDB
并且不存在模式验证,AggregateRoot
存储在 MongoDB 中的 The 和 Document 类是两个不同的类,并且Repository
在读取和写入数据时在这两个类之间转换内容database
。
由于 Root 实体类与存储到 DB 的类不同,因此 Spring 不会触发DomainEvents
.AggregateRoot
将数据存储到数据库后,有没有办法可以从存储库中触发根实体的事件?(也许通过显式调用)
因为 MongoDB 和 Aggregates 是 1:1 的。那么这是否意味着我们通常不应该将两个不同的类作为
AggregateRoot
一个文档类,另一个作为文档类用于在 mongoDB 中存储聚合根?难道我们不需要在我们的聚合之上添加@Document 注释,这会泄漏我们领域模型中的基础设施代码吗?
解决方案
过了一会儿,我找到了解决方案,从投票中我相信其他人也面临同样的问题,这里是解决方案:
问题:我们可以触发领域事件的显式调用吗?
答:是的,我们可以。在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
分开并保持不可知论。如果它们都相同,则影响如下:infrastructure
Domain
Domain
- 如果
@Document
您Aggregate Class
要Domain
切换框架或Mongodb
与SQL
. - 将来如果您的数据库架构需要更改,您将不得不更改您的聚合类,或者您必须设置适配器类。
- 由于领域应该只在业务需求发生变化而不是因为发生变化时才发生变化,
infrastructure dependencies
因此infrastructure annotations
潜入其中AggregateRoot
并不是最好的方法
如果您确实想保持简单并为两者使用相同的类而不是创建单独的类,请确保您确定以下内容:
- 如果您绝对确定您永远不会切换数据库或更改框架。
- 您有一个简单的域模型,您不需要将其存储
Entities
在Aggregate
单独的集合中,并且您不可能Entities
将它们变成自己的Aggregates
最终取决于。随意发表评论,我会尽力回答所有问题,在堆栈上非常活跃。
推荐阅读
- javascript - 在 evo 日历中设置当前日期的默认日期
- python - 导入代码在本地计算机上工作正常,但在 aws 上出错
- c++ - 运行 cmake 时,`No CMAKE_ASM_COMPILER found` 错误
- laravel - Laravel Lighthouse 限制突变场
- jquery - 需要一个不工作的 JQuery 函数
- autodesk-forge - Autodesk.Viewing.UI.DataTable 压垮其他 DataTable
- python - 如何在python中选择不同比例的随机数?
- reactjs - axios 无法在 reactjs 中获取 public/[name].json 文件夹
- c# - 如何将docusign草稿信封按顺序发送给收件人?
- office-js - @microsoft/office-js 模块未找到