我正在使用 DDD
和 Spring
使用 MongoDB
。
现在 MongoDB
是一个 DocumentDB
并且不存在模式验证,AggregateRoot
和存储在 MongoDB 中的文档类是两个不同的类,Repository
在读取和写入数据到 database
时在这两个类之间转换内容。
由于Root实体类与存储到DB的类不同,Spring不会触发AggregateRoot
的DomainEvents
。
在将数据存储到数据库后,有没有一种方法可以从存储库中触发根实体的事件? (可能通过显式调用)
因为 MongoDB 和聚合是 1:1 的组合。那么这是否意味着我们通常不应该创建两个不同的类,一个是
AggregateRoot
另一个是用于在 mongoDB 中存储聚合根的文档类?难道我们不必在我们的聚合顶部添加 @Document 注释,这会泄漏我们领域模型中的基础设施代码吗?
最佳答案
一段时间后我找到了解决方案,从投票中我相信其他人也面临着同样的问题,这是解决方案:
问题:我们可以触发领域事件的显式调用吗?
回答:是的,我们可以。在 SpringBoot
我们可以使用/Autowire
ApplicationEventPublisher
界面然后调用publishEvent(event)
方法。
如果您正在为 Db 集合和聚合创建一个单独的类,您需要公开您的 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
最终取决于。欢迎发表评论,我会尽力回答所有问题,在堆栈上非常活跃。
关于java - 使用 Spring Boot 和 MongoDB 的领域事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61632788/