问题描述
所以我正在学习轴突框架,只是想巩固我对 @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 - 这会告诉 axon 框架这是标识符,因此当引入更多命令时,它需要存储该特定聚合的事件?
如果有人能指出我的理解是否正确并评论不正确的地方,我将不胜感激,以便我能够以正确的方式使用该框架。
谢谢。
解决方法
我已经在最初发布问题的 AxonIQ 讨论平台上提供了一个 answer。
因为用链接回答只会违反 SO 的礼仪,所以我也在这里回答:
我猜你的理解是正确的。但让我给你一个 该过程的简化解释,以便您可以将其与您的 目前的理解。
当您发出创建新聚合的命令 (即
由聚合的构造函数处理) 不需要
标识符。原因是您正在创建一个新实例,而不是加载
一个现有的。在这种情况下,框架只需要
聚合以创建它的实例。它可以很容易地找到
FQCN 因为它知道(从聚合期间的检查中
注册)哪个聚合可以处理这样的创建命令。那是
为什么创建没有 @TargetAggregateIdentifier
的命令只是工作
很好。
一旦创建命令被处理,聚合的状态需要是 存储在某处。
- 对于事件源聚合,所有状态更改事件都存储在事件存储中
- 对于状态存储聚合,整个状态存储在存储库中
在这两种情况下,框架都需要知道如何识别这些数据。
这就是 @AggregateIdentifier
的用途。它告诉框架
以可通过特定标识符识别的方式存储数据。
您可以将其视为 DB 术语中的主键。
当您向聚合的现有实例发送命令时
需要告诉这是哪个实例。您可以通过提供一个
@TargetAggregateIdentifier
。然后框架将创建一个新的
相应聚合的空实例,然后尝试加载
数据进去
- 通过读取与该实例相关的所有过去事件来获取事件源聚合
- 通过从存储库读取当前状态用于状态存储聚合
在这两种情况下,框架都会搜索可识别的数据
通过 @TargetAggregateIdentifier
的值。一旦汇总数据
加载后,它将继续处理命令。