首页 > 解决方案 > @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 - 这告诉轴突框架这是标识符,因此当引入更多命令时,它需要存储该特定聚合的事件?

如果有人能指出我的理解是否正确并在不正确的地方发表评论,我将不胜感激,以便我可以以正确的方式使用该框架。

谢谢。

标签: cqrsevent-sourcingaxonaxon-framework

解决方案


我已经在最初发布问题的 AxonIQ 讨论平台上提供了答案。

由于使用链接回答只会违反 SO 的礼仪,因此我也在这里应对我的回答:

我猜你的理解是正确的。但是让我给你一个简化的过程解释,这样你就可以将它与你当前的理解进行比较。

当您发出一个创建新聚合的命令(由聚合的构造函数处理的)时,不需要标识符。原因是您正在创建一个新实例,而不是加载现有实例。在这种情况下,框架只需要聚合的 FQCN 来创建它的实例。它可以很容易地找到 FQCN,因为它知道(从聚合注册期间的检查)哪个聚合可以处理这样的创建命令。@TargetAggregateIdentifier这就是为什么无需工作就可以创建命令的原因。

处理完创建命令后,需要将聚合的状态存储在某处。

  • 对于事件源聚合,所有状态更改事件都存储在事件存储中
  • 对于状态存储聚合,整个状态存储在存储库中

在这两种情况下,框架都需要知道如何识别这些数据。这@AggregateIdentifier就是为了。它告诉框架以可通过特定标识符识别的方式存储数据。您可以将其视为数据库术语中的主键。

当您向聚合的现有实例发送命令时,您需要告诉它是哪个实例。您可以通过提供 @TargetAggregateIdentifier . 然后,框架将创建相应聚合的新空实例,然后尝试将数据加载到其中

  • 通过读取与该实例相关的所有过去事件来获取事件源聚合
  • 通过从存储库中读取当前状态来获取状态存储的聚合

在这两种情况下,框架都将搜索可通过 的值识别的数据@TargetAggregateIdentifier。加载聚合数据后,它将继续处理命令。


推荐阅读