Axon - 我的聚合 equal/be 的唯一 ID 是否与我的实体的相同?
Axon - Does the unique Id of my Aggregate equal/be the same as that of my Entity?
我一定是哪里做错了。
我有一个非常简单的 Axon 应用程序,它有两个简单的功能:创建一个人并更改这个人的名字。
所以我有个人实体:
@Entity
@Data
@NoArgsConstructor
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
}
还有我的 PersonAggregate:
@Aggregate
@Data
@NoArgsConstructor
public class PersonAggregate {
@AggregateIdentifier
private UUID id;
private String name;
@CommandHandler
public PersonAggregate(CreatePersonCommand command) {
apply(new PersonCreatedEvent(
command.getId(),
command.getName()
));
}
@EventSourcingHandler
public void on(PersonCreatedEvent event) {
this.id = event.getId();
this.name = event.getName();
}
@CommandHandler
public void handle(ChangeNameCommand command) {
apply(
new NameChangedEvent(
command.getId(),
command.getName()
)
);
}
@EventSourcingHandler
public void on(NameChangedEvent event) {
this.name = event.getName();
}
}
这是我的 ChangeNameCommand:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ChangeNameCommand {
@TargetAggregateIdentifier
private UUID id;
private String name;
}
这是我的 NameChangedEvent:
@Value
public class NameChangedEvent {
private final UUID id;
private final String name;
}
和存储库:
@Repository
public interface PersonCommandRepository extends JpaRepository<Person, Long> {
}
问题 是我不确定如何构造我的事件处理程序
@EventHandler
public void changeName(NameChangedEvent event) {
Optional<Person> opt = null;//this.personCommandRepository.findById(event.getId());
if (opt.isPresent()) {
Person person = opt.get();
person.setName(event.getName());
this.personCommandRepository.save(person); //Does'nt this defeat the purpose of Event Sourcing? A single point of truth?
}
而且,在我的控制器中,我有一个很大的问题,在评论中:
@RequestMapping(value = "/rename", method = RequestMethod.POST)
public ResponseEntity<?> changeName(@RequestParam("id") Long id, @RequestParam("name")String name){
//1. Which Id do we pass in here? Aggregate or Entity?
//this.commandGateway.send(new ChangeNameCommand(id,name));
return new ResponseEntity<String>("Renamed", HttpStatus.OK);
}
}
我觉得您仍在将命令模型和查询模型的想法混为一谈。
通常是聚合(或多个)的命令模型仅处理更改某些状态的意图请求。因此,这些意图请求(即命令消息)是针对您的 aggregate/command 模型的唯一操作。反之亦然,如果你需要改变一个人的某些东西,这意味着你发送一个命令来标记这个意图 PersonAggregate
.
另一方面,查询模型仅负责回答针对您的应用程序的问题。如果以某种方式需要知道一个人的状态,这意味着您向能够返回您共享的 Person
实体的组件发送查询。
回到 "the problems" 你描述了:
- "Doesn't this defeat the purpose of Event Sourcing? A single point of truth?":事件溯源是一个特定于从事件 中补充 命令模型 的概念本身 已发布。因此,使用事件溯源仅意味着您确定不仅您的查询模型是通过事件创建的,而且您的命令模型也是如此。因此,您这样做是在强制执行单一的事实来源。因此,使用事件更新查询模型不会破坏 ES 的目的。
- "Which Id do we pass in here? Aggregate or Entity?":当你有疑问时,试着弄清楚你想要达到什么。你是在索取信息吗?然后它是针对您的查询模型的查询。是否打算将某些状态更改为模型?然后向命令模型发送命令。在这个确切的场景中,您想要更改一个人的名字。因此,您向 Aggregate/Command 模型发送命令。
在 AxonIQ 的网页上有一个 Architectural Concepts section describing all the main principles. There's also one about CQRS 可能有帮助。
可能有助于阅读这些;很确定其中很多将解决您的很多问题。 :-)
希望对您有所帮助!
我一定是哪里做错了。
我有一个非常简单的 Axon 应用程序,它有两个简单的功能:创建一个人并更改这个人的名字。
所以我有个人实体:
@Entity
@Data
@NoArgsConstructor
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
}
还有我的 PersonAggregate:
@Aggregate
@Data
@NoArgsConstructor
public class PersonAggregate {
@AggregateIdentifier
private UUID id;
private String name;
@CommandHandler
public PersonAggregate(CreatePersonCommand command) {
apply(new PersonCreatedEvent(
command.getId(),
command.getName()
));
}
@EventSourcingHandler
public void on(PersonCreatedEvent event) {
this.id = event.getId();
this.name = event.getName();
}
@CommandHandler
public void handle(ChangeNameCommand command) {
apply(
new NameChangedEvent(
command.getId(),
command.getName()
)
);
}
@EventSourcingHandler
public void on(NameChangedEvent event) {
this.name = event.getName();
}
}
这是我的 ChangeNameCommand:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ChangeNameCommand {
@TargetAggregateIdentifier
private UUID id;
private String name;
}
这是我的 NameChangedEvent:
@Value
public class NameChangedEvent {
private final UUID id;
private final String name;
}
和存储库:
@Repository
public interface PersonCommandRepository extends JpaRepository<Person, Long> {
}
问题 是我不确定如何构造我的事件处理程序
@EventHandler
public void changeName(NameChangedEvent event) {
Optional<Person> opt = null;//this.personCommandRepository.findById(event.getId());
if (opt.isPresent()) {
Person person = opt.get();
person.setName(event.getName());
this.personCommandRepository.save(person); //Does'nt this defeat the purpose of Event Sourcing? A single point of truth?
}
而且,在我的控制器中,我有一个很大的问题,在评论中:
@RequestMapping(value = "/rename", method = RequestMethod.POST)
public ResponseEntity<?> changeName(@RequestParam("id") Long id, @RequestParam("name")String name){
//1. Which Id do we pass in here? Aggregate or Entity?
//this.commandGateway.send(new ChangeNameCommand(id,name));
return new ResponseEntity<String>("Renamed", HttpStatus.OK);
}
}
我觉得您仍在将命令模型和查询模型的想法混为一谈。
通常是聚合(或多个)的命令模型仅处理更改某些状态的意图请求。因此,这些意图请求(即命令消息)是针对您的 aggregate/command 模型的唯一操作。反之亦然,如果你需要改变一个人的某些东西,这意味着你发送一个命令来标记这个意图 PersonAggregate
.
另一方面,查询模型仅负责回答针对您的应用程序的问题。如果以某种方式需要知道一个人的状态,这意味着您向能够返回您共享的 Person
实体的组件发送查询。
回到 "the problems" 你描述了:
- "Doesn't this defeat the purpose of Event Sourcing? A single point of truth?":事件溯源是一个特定于从事件 中补充 命令模型 的概念本身 已发布。因此,使用事件溯源仅意味着您确定不仅您的查询模型是通过事件创建的,而且您的命令模型也是如此。因此,您这样做是在强制执行单一的事实来源。因此,使用事件更新查询模型不会破坏 ES 的目的。
- "Which Id do we pass in here? Aggregate or Entity?":当你有疑问时,试着弄清楚你想要达到什么。你是在索取信息吗?然后它是针对您的查询模型的查询。是否打算将某些状态更改为模型?然后向命令模型发送命令。在这个确切的场景中,您想要更改一个人的名字。因此,您向 Aggregate/Command 模型发送命令。
在 AxonIQ 的网页上有一个 Architectural Concepts section describing all the main principles. There's also one about CQRS 可能有帮助。 可能有助于阅读这些;很确定其中很多将解决您的很多问题。 :-)
希望对您有所帮助!