cqrs - @AggregateIdentifier & @TargetAggregateIdentifier 的理解
问题描述
所以我正在学习轴突框架,只是想巩固我对@TargetAggregateIdentifier
注释的理解。
我的命令:
public class IssueCardCommand {
private String cardId;
private String versionNumber;
private Integer amount;
@TargetAggregateIdentifier
private String getAggregateIdentifier() {
return (null != versionNumber) ? cardId + "V" + versionNumber : cardId;
}
}
我的汇总:
@Aggregate
@Slf4j
public class GiftCard {
private String giftCardId;
private String versionNumber;
private Integer amount;
@AggregateIdentifier
private String getAggregateIdentifier() {
return (null != versionNumber) ? giftCardId + "V" + versionNumber : giftCardId;
}
public GiftCard() {
log.info("empty noargs constructor");
}
@CommandHandler
public GiftCard(IssueCardCommand cmd) {
log.info("handling {}",cmd);
//this.giftCardId = cmd.getCardId();
//this.versionNumber = cmd.getVersionNumber();
apply(new CardIssuedEvent(cmd.getCardId(),cmd.getVersionNumber(),cmd.getAmount()));
}
@EventSourcingHandler
public void onCardIssuedEvent(CardIssuedEvent evt) {
log.info("applying {}",evt);
this.giftCardId = evt.getCardId();
this.versionNumber = evt.getVersionNumber();
this.amount = evt.getAmount();
}
}
所以这一切都按预期工作,并且事件被正确存储。但是,我只想确保我正确理解了 @TargetAggregateIdentifier 和 @AggregateIdentifier 注释。
所以
@TargetAggregateIdentifier - 命令转到聚合的特定实例,因此需要告诉框架它是哪个实例,因此字段/方法上的此注释用于加载该特定聚合的事件?
我注意到,当我在构造函数的命令中没有 @TargetAggregateIdentifier 时,代码仍然有效。但是,如果它在任何后续命令中丢失,它会给出错误“无效命令,它无法识别目标聚合”,我觉得这证实了我上面的理解?
@AggregateIdentifier - 这告诉轴突框架这是标识符,因此当引入更多命令时,它需要存储该特定聚合的事件?
如果有人能指出我的理解是否正确并在不正确的地方发表评论,我将不胜感激,以便我可以以正确的方式使用该框架。
谢谢。
解决方案
我已经在最初发布问题的 AxonIQ 讨论平台上提供了答案。
由于使用链接回答只会违反 SO 的礼仪,因此我也在这里应对我的回答:
我猜你的理解是正确的。但是让我给你一个简化的过程解释,这样你就可以将它与你当前的理解进行比较。
当您发出一个创建新聚合的命令(由聚合的构造函数处理的)时,不需要标识符。原因是您正在创建一个新实例,而不是加载现有实例。在这种情况下,框架只需要聚合的 FQCN 来创建它的实例。它可以很容易地找到 FQCN,因为它知道(从聚合注册期间的检查)哪个聚合可以处理这样的创建命令。
@TargetAggregateIdentifier
这就是为什么无需工作就可以创建命令的原因。处理完创建命令后,需要将聚合的状态存储在某处。
- 对于事件源聚合,所有状态更改事件都存储在事件存储中
- 对于状态存储聚合,整个状态存储在存储库中
在这两种情况下,框架都需要知道如何识别这些数据。这
@AggregateIdentifier
就是为了。它告诉框架以可通过特定标识符识别的方式存储数据。您可以将其视为数据库术语中的主键。当您向聚合的现有实例发送命令时,您需要告诉它是哪个实例。您可以通过提供
@TargetAggregateIdentifier
. 然后,框架将创建相应聚合的新空实例,然后尝试将数据加载到其中
- 通过读取与该实例相关的所有过去事件来获取事件源聚合
- 通过从存储库中读取当前状态来获取状态存储的聚合
在这两种情况下,框架都将搜索可通过 的值识别的数据
@TargetAggregateIdentifier
。加载聚合数据后,它将继续处理命令。
推荐阅读
- c# - Linq - 按价格双倍订购 Json 产品
- python - django 和 html 输出
- android - Android Studio 中 jpg 文件的“文件名必须以 .xml 结尾”错误
- java - 有没有办法在用 Java 关闭客户端连接后重用它的端口?
- reactjs - TypeError: Object(...) is not a function while using React Hooks
- javascript - 我尝试在 heroku 上部署 NodeJS 应用程序,但无法从外部路由器发出请求
- firebase - Flutter:来自 Firestore 的项目在刷新之前未显示在 GridView 中
- python - 在pygame中动画精灵的问题
- cookies - 使用 lua 从网站获取 cookie [不是特定的 cookie / 原始代码]
- google-calendar-api - 在什么情况下,iCal VEVENT 最终会出现重复的 UID?