公平警告:我不知道我在做什么,所以即使问这个问题也可能会出错。
我想要更新一个简单对象(聚合)的状态,然后向 UI 提供已更改对象的投影。这是我的聚合对象(命令处理程序存在,但此处未显示)。
@Aggregate
public class Widget {
@AggregateIdentifier
private String id;
private String color;
...
@EventSourcingHandler
public void on(ChangeColorEvt evt) {
color = evt.getColor();
}
...
}
...这是我的预测:
public class WidgetProjection {
private final EntityManager entityManager;
private final QueryUpdateEmitter queryUpdateEmitter;
...
@EventHandler
public void on(ChangeColorEvt evt) {
ProjectedWidget projection = entityManager.find(ProjectedWidget.class, evt.getId());
projection.setColor(evt.getColor());
queryUpdateEmitter.emit(FetchWidget.class, query -> evt.getId().startsWith(query.getFilter().getIdStartsWith()), projection);
}
...
}
QueryHandler 执行您所期望的操作,查找实例并返回它。
这是我的问题:
- 为什么聚合中需要 EventSourcingHandler?这就对了
似乎可以工作,但结果不会存储或发送到任何地方。
- 所以,这成为我的下一个问题:执行 EventSourcing 后
Handler,是 Widget 的结果实例(不是投影)
存储、查看或发送到任何地方?
- 如果确实需要EventSourcingHandler,有什么办法可以避免
我的业务逻辑有两个独立的副本(一个在
EventSourcingHandler 和一个 EventHandler)?我真的很讨厌这个主意
必须在两个地方更新相同的业务逻辑。
我很感谢该小组能够提供的任何澄清。感谢您的帮助!
我希望我能帮助你解答这个问题!
简短的回答是:
使用的必要性@EventSourcingHandler
实际上取决于您想要如何对应用程序进行建模。
现在,这并没有说明太多,所以让我详细说明一下为什么我这么说。
在回答您的问题时,我假设您的愿望是创建一个遵循 DDD、CQRS 和事件溯源思想的应用程序。因此,Axon 试图在构建应用程序时为您简化概念。
让我从这里回顾一下您的编号问题:
- 你需要的原因
@EventSourcingHandler
聚合中带注释的函数,是 (1) 根据 (2) 事件更新聚合状态it已发布。转到第 1 点,为什么要更新聚合的状态?由于聚合是应用程序的命令模型,因此它的任务是根据收到的命令做出决策。为了能够做出决策,有时聚合需要状态,但有时则不需要。所以在Widget
你分享的例子,我假设color
字段稍后根本不用于驱动业务逻辑,因此您可以完全从聚合中忽略此状态,不会出现任何问题。对于我的回应的第二点,我试图指出聚合只会处理源自自身的事件。这是因为事件是聚合的来源,因为事件构成了给定模型上发生的所有增量。
- 您的以下问题非常适合继续我在第 1 点中开始的解释。答案很简单,您的
Widget
聚合不存储在任何地方,不as is。每次您从以下位置检索聚合时Repository
(这在 Axon 中会自动为您完成),默认为EventSourcingRepository
在 Axon 中,将从事件存储中检索该给定聚合的所有事件。比,一个empty创建聚合实例,框架将重播它为该确切聚合实例找到的所有事件。因此,每次输入新命令时,您都会有效地对聚合进行事件溯源。这可能听起来有点矫枉过正,因为给定聚合的事件数量可能会增长到相当大的集合。这可以通过做类似的事情来解决快照 https://docs.axoniq.io/reference-guide/axon-framework/tuning/event-snapshots的聚合。
- 如果这种形式将您的应用程序拆分为处理业务逻辑的专用部分(命令模型)和仅返回查询模型作为答案的部分(查询模型),那么您可以决定采用状态存储聚合 https://docs.axoniq.io/reference-guide/implementing-domain-logic/command-handling/state-stored-aggregates。因此请注意,使用 Axon 时根本不需要进行事件溯源;这只是框架的默认操作方式。因此,我理解你的担忧,因为你在重复你的逻辑。但是,您可以严格分离做出要在聚合中保存的所有决策的部分。
查询模型(在您的示例中
ProjectedWidget
)可以以任何格式存储在您想要的任何数据库/工具中,理想情况下没有任何业务逻辑。
如果您确实发现自己在应用程序的查询端添加业务逻辑,这可能建议您应该将此位升级为源自聚合的事件。
我希望这能让您深入了解为什么要选择事件溯源。本文描述了CQRS https://axoniq.io/resources/cqrs比我在这里能做的更详细一点,并且this https://axoniq.io/resources/event-sourcing事件溯源链接;希望它们可以作为比我刚才给你的更彻底的解释。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)