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" 你描述了:

  1. "Doesn't this defeat the purpose of Event Sourcing? A single point of truth?":事件溯源是一个特定于从事件 中补充 命令模型 的概念本身 已发布。因此,使用事件溯源仅意味着您确定不仅您的查询模型是通过事件创建的,而且您的命令模型也是如此。因此,您这样做是在强制执行单一的事实来源。因此,使用事件更新查询模型不会破坏 ES 的目的。
  2. "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 可能有帮助。 可能有助于阅读这些;很确定其中很多将解决您的很多问题。 :-)

希望对您有所帮助!