axon - 应用事件后,聚合标识符必须为非空。确保聚合标识符最迟初始化
问题描述
我收到以下错误。轴突版本 3.3.3
org.axonframework.eventsourcing.IncompatibleAggregateException:应用事件后聚合标识符必须为非空。确保在处理创建事件时最迟初始化聚合标识符。
我创建了一个用户聚合。它包含 2 个事件:
- 用户创建
- 更新用户事件
我能够生成第一个 (UserCreated) 事件,它以序列 0 保存在事件存储中,但是在生成第二个事件时,我得到了上述错误。
对此有何建议?
用户聚合.java
@Aggregate
public class UserAggregate {
@AggregateIdentifier
private String id;
private String email;
private String password;
public UserAggregate(String id, String email, String password) {
super();
this.id = id;
this.email = email;
this.password = password;
}
@CommandHandler
public UserAggregate(CreateUser cmd) {
AggregateLifecycle.apply(new UserCreated(cmd.getId(), cmd.getEmail(), cmd.getPassword()));
}
@CommandHandler
public void handle(UpdateUserCmd cmd) {
AggregateLifecycle.apply(new UpdateUserEvent(cmd.getId(), cmd.getEmail(),""));
}
@EventSourcingHandler
public void userCreated(UserCreated event) {
System.out.println("new User: email " + event.getEmail() +" Password: "+ event.getPassword());
setId(event.getId());
}
@EventSourcingHandler
public void updateUserEvent(UpdateUserEvent event) {
System.out.println("new User: email " + event.getEmail());
setId(event.getId());
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public UserAggregate() {
}
}
解决方案
我仍在了解 Axon,但这是我设法解决问题的方法。基本上错误的意思是,当UserAggregate
被实例化时,聚合标识符(又名主键)不能为空并且必须有一个值。
生命周期的顺序是
- 它调用无参数构造函数
- 在您的情况下,它会使用您的初始命令调用构造函数。此时,您的聚合标识符仍然为空,我们将在下一步中分配一个值
- 然后它调用 a
EventSourcingHandler
来处理您在上一步中应用的事件
根据上述步骤,您需要执行以下操作:
- 创建一个无参数构造函数
protected UserAggregate() {
}
- 创建一个处理您的第一个命令的构造函数:
@CommandHandler
public UserAggregate(CreateUser cmd) {
AggregateLifecycle.apply(
new UserCreated(cmd.getId(),cmd.getEmail(),cmd.getPassword()));
}
- 最后添加一个事件源处理程序来处理
UserCreated
事件
@EventSourcingHandler
public void on(UserCreated userCreated) {
// this is where we instantiate the aggregate identifier
this.id = userCreated.getId();
//assign values to other fields
this.email = userCreated.getEmail();
this.password = userCreated.getPassword();
}
这是完整的示例:
@Aggregate
public class UserAggregate {
@AggregateIdentifier
private String id;
private String password;
private String email;
protected UserAggregate() {
}
@CommandHandler
public UserAggregate(CreateUser cmd) {
AggregateLifecycle.apply(
new UserCreated(cmd.getId(),cmd.getEmail(),cmd.getPassword()));
}
@EventSourcingHandler
public void on(UserCreated userCreated) {
// this is where we instantiate the aggregate identifier
this.id = userCreated.getId();
//assign values to other fields
this.email = userCreated.getEmail();
this.password = userCreated.getPassword();
}
}
推荐阅读
- python - 将数据帧与具有来自第一个数据帧的常量值的另一个数据帧合并
- r - 将多个类别识别的字符/字符串转换为单独的字符串
- neo4j - 如何在密码中包含失败的匹配值
- ruby - 如何解决“retrieve_values”问题
- asp.net-core - 如何从 ASP.NET Core 中的控制器操作提供 Blazor 应用程序
- ruby-on-rails - Solidus - 无法上传或查看图像(已安装 ImageMagick)
- qt - 如何将 QString 转换为 ascii?
- python - Selenium 网站登录脚本。- 安全地存储凭据
- javascript - Angular Animation 不断在每个动作上重新启动
- rest - 使用 REST api 更新 Sharepoint 元数据会出现 400 错误请求错误