多实体聚合命令处理
Multi-entity Aggregates command handling
我有一个这样的聚合根:
聚合根:
@NoArgsConstructor
@Aggregate(repository = "positionAggregateRepository")
@AggregateRoot
@XSlf4j
@Data
public class HopAggregate {
@AggregateIdentifier
private String hopId;
private FilteredPosition position;
private LocalDate positionDate;
@AggregateMember
private Security security;
@CommandHandler
public HopAggregate(NewHopCommand cmd) {
log.info("creating new position , {}", cmd.getDateId());
apply(new HopEvent(cmd.getHopId(), cmd.getDateId(), cmd.getFilteredPosition(), cmd.getSecurity(), false));
}
@CommandHandler
public void handle(UpdateHopCommand cmd) {
log.info("creating hop update event {}", cmd);
apply(new HopEvent(this.hopId, this.positionDate, cmd.getFilteredPosition(), this.security, true));
}
@CommandHandler
public void handle(SecurityUpdate cmd) {
log.info("updating security {}", cmd);
apply(new SecurityUpdateEvent(this.hopId, cmd.getFilteredSecurity()));
}
@EventSourcingHandler
public void on(HopEvent evt) {
if (evt.getIsUpdate()) {
log.info("updating position {}", evt);
this.position = evt.getFilteredPosition();
} else {
log.info("adding new position to date {}", evt);
this.hopId = evt.getHopId();
this.positionDate = evt.getDate();
this.position = evt.getFilteredPosition();
this.security= evt.getSecurity();
}
}
@EventSourcingHandler
public void on(SecurityUpdateEvent evt) {
log.info("hop id {}, security update {}", this.hopId, evt.getFilteredSecurity().getSecurityId());
}
}
子实体:
@XSlf4j
@Data
@RequiredArgsConstructor
@NoArgsConstructor
public class IpaSecurity implements Serializable {
@EntityId
@NonNull
private String id;
@NonNull
private FilteredSecurity security;
}
我的问题是,当我像这样推送和更新时:
@EventHandler
public void handleSecurityEvent(SecurityUpdate securityUpdate) {
log.info("got security event {}", securityUpdate);
commandGateway.send(securityUpdate);
}
我的命令是:
@Data
@RequiredArgsConstructor
@NoArgsConstructor
@ToString
public class SecurityUpdate {
@NonNull
@TargetAggregateIdentifier
private String id;
@NonNull
private FilteredSecurity filteredSecurity;
}
我收到聚合根未找到异常:
命令 'com.hb.apps.ipa.events.SecurityUpdate' 导致 org.axonframework.modelling.command.AggregateNotFoundException(在事件存储中找不到聚合)
我不确定如何处理这种情况。我的要求是每个聚合都应检查它是否包含安全性,然后在发出命令时更新它。我错过了什么?如果您需要有关代码的更多信息,请告诉我。
感谢您的帮助。
命令总是针对单个实体。
该实体可以是聚合、包含在聚合中的实体(Axon 框架称为聚合成员)或简单的单例组件。
不过需要注意的是,只有一个 实体处理命令。
这就是要求您在命令中设置 @TargetAggregateIdentifier
的原因,以便 Axon 能够将其路由到单个聚合实例(如果有问题的命令处理程序是其中的一部分)。
您收到的 AggregateNotFoundException
信号表明您的 SecurityUpdate
命令中的 @TargetAggregateIdentifier
注释字段不对应于任何现有聚合。
因此,我怀疑 SecurityUpdate
中的 id
字段与 HopAggregate
聚合中的任何 @AggregateIdentifier
注释字段不对应。
根据以上内容,我在查看您的代码片段时还有其他一些建议想与您分享:
@Aggregate
是 meta-annotated 和 @AggregateRoot
。因此,您不需要在聚合 class 上指定两者
- 对于正在处理的日志消息,您可以使用
LoggingInterceptor
。您可以在任何能够处理消息的组件上配置它,从而提供一种通用的日志记录方式。这将省略在消息处理函数中添加日志行的必要性
- 您正在对创建和更新命令发布
HopEvent
。这样做会使您的 HopEvent
非常通用。理想情况下,您的事件会阐明系统中发生的业务操作。我的经验法则通常是这样的:"If I tell my business manager/customer about the event class, he/she should know exactly what it does"。因此,我建议将事件重命名为更具体的名称
- 与
HopEvent
一样,UpdateHopCommand
非常通用。您的命令应该表达在您的应用程序中执行操作的意图。用户通常不希望更新,例如,他们希望更改地址。您的命令 classes 完美地反映了这一点
- 建议的命令命名约定是以现在时的动词开头。因此,它不应该是
SecurityUpdate
,而是 UpdateSecurity
。命令是表达意图的请求,消息理想地反映了这一点
希望这对你有帮助 @juggernaut!
我有一个这样的聚合根:
聚合根:
@NoArgsConstructor
@Aggregate(repository = "positionAggregateRepository")
@AggregateRoot
@XSlf4j
@Data
public class HopAggregate {
@AggregateIdentifier
private String hopId;
private FilteredPosition position;
private LocalDate positionDate;
@AggregateMember
private Security security;
@CommandHandler
public HopAggregate(NewHopCommand cmd) {
log.info("creating new position , {}", cmd.getDateId());
apply(new HopEvent(cmd.getHopId(), cmd.getDateId(), cmd.getFilteredPosition(), cmd.getSecurity(), false));
}
@CommandHandler
public void handle(UpdateHopCommand cmd) {
log.info("creating hop update event {}", cmd);
apply(new HopEvent(this.hopId, this.positionDate, cmd.getFilteredPosition(), this.security, true));
}
@CommandHandler
public void handle(SecurityUpdate cmd) {
log.info("updating security {}", cmd);
apply(new SecurityUpdateEvent(this.hopId, cmd.getFilteredSecurity()));
}
@EventSourcingHandler
public void on(HopEvent evt) {
if (evt.getIsUpdate()) {
log.info("updating position {}", evt);
this.position = evt.getFilteredPosition();
} else {
log.info("adding new position to date {}", evt);
this.hopId = evt.getHopId();
this.positionDate = evt.getDate();
this.position = evt.getFilteredPosition();
this.security= evt.getSecurity();
}
}
@EventSourcingHandler
public void on(SecurityUpdateEvent evt) {
log.info("hop id {}, security update {}", this.hopId, evt.getFilteredSecurity().getSecurityId());
}
}
子实体:
@XSlf4j
@Data
@RequiredArgsConstructor
@NoArgsConstructor
public class IpaSecurity implements Serializable {
@EntityId
@NonNull
private String id;
@NonNull
private FilteredSecurity security;
}
我的问题是,当我像这样推送和更新时:
@EventHandler
public void handleSecurityEvent(SecurityUpdate securityUpdate) {
log.info("got security event {}", securityUpdate);
commandGateway.send(securityUpdate);
}
我的命令是:
@Data
@RequiredArgsConstructor
@NoArgsConstructor
@ToString
public class SecurityUpdate {
@NonNull
@TargetAggregateIdentifier
private String id;
@NonNull
private FilteredSecurity filteredSecurity;
}
我收到聚合根未找到异常:
命令 'com.hb.apps.ipa.events.SecurityUpdate' 导致 org.axonframework.modelling.command.AggregateNotFoundException(在事件存储中找不到聚合)
我不确定如何处理这种情况。我的要求是每个聚合都应检查它是否包含安全性,然后在发出命令时更新它。我错过了什么?如果您需要有关代码的更多信息,请告诉我。
感谢您的帮助。
命令总是针对单个实体。 该实体可以是聚合、包含在聚合中的实体(Axon 框架称为聚合成员)或简单的单例组件。 不过需要注意的是,只有一个 实体处理命令。
这就是要求您在命令中设置 @TargetAggregateIdentifier
的原因,以便 Axon 能够将其路由到单个聚合实例(如果有问题的命令处理程序是其中的一部分)。
您收到的 AggregateNotFoundException
信号表明您的 SecurityUpdate
命令中的 @TargetAggregateIdentifier
注释字段不对应于任何现有聚合。
因此,我怀疑 SecurityUpdate
中的 id
字段与 HopAggregate
聚合中的任何 @AggregateIdentifier
注释字段不对应。
根据以上内容,我在查看您的代码片段时还有其他一些建议想与您分享:
@Aggregate
是 meta-annotated 和@AggregateRoot
。因此,您不需要在聚合 class 上指定两者
- 对于正在处理的日志消息,您可以使用
LoggingInterceptor
。您可以在任何能够处理消息的组件上配置它,从而提供一种通用的日志记录方式。这将省略在消息处理函数中添加日志行的必要性 - 您正在对创建和更新命令发布
HopEvent
。这样做会使您的HopEvent
非常通用。理想情况下,您的事件会阐明系统中发生的业务操作。我的经验法则通常是这样的:"If I tell my business manager/customer about the event class, he/she should know exactly what it does"。因此,我建议将事件重命名为更具体的名称 - 与
HopEvent
一样,UpdateHopCommand
非常通用。您的命令应该表达在您的应用程序中执行操作的意图。用户通常不希望更新,例如,他们希望更改地址。您的命令 classes 完美地反映了这一点 - 建议的命令命名约定是以现在时的动词开头。因此,它不应该是
SecurityUpdate
,而是UpdateSecurity
。命令是表达意图的请求,消息理想地反映了这一点
希望这对你有帮助 @juggernaut!