首页 > 解决方案 > Axon - 我的聚合的唯一 ID 是否与我的实体的唯一 ID 相同/相同?

问题描述

我一定在这里做错了什么。

我有一个非常简单的 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);
    }

}

标签: javaspring-bootmicroservicesaxon

解决方案


我觉得您仍在将命令模型和查询模型的概念混为一谈。

命令模型,通常是聚合(或多个),仅处理意图更改某些状态的请求。因此,这些意图请求(即命令消息)是针对您的聚合/命令模型的唯一操作。反之亦然,如果您需要更改 Person 上的某些内容,则意味着您向PersonAggregate.

另一方面,查询模型的唯一任务是回答针对您的应用程序的问题。如果以某种方式需要知道 Person 的状态,这意味着您向能够返回Person您共享的实体的组件发送查询。

回到你描述的“问题”:

  1. “这不是违背了事件溯源的目的吗?单点真理?” :事件溯源是一个特定于从事件本身已发布的事件中补充命令模型的概念。因此,使用事件溯源仅意味着您确定不仅您的查询模型是通过事件创建的,而且您的命令模型也是如此。因此,您这样做是在强制执行单一的事实来源。因此,使用事件来更新查询模型不会违背 ES 的目的。
  2. “我们在这里传入哪个 ID?聚合还是实体?” :当您有疑问时,请尝试弄清楚您想要实现的目标。你要信息吗?然后它是针对您的查询模型的查询。是否打算将某些状态更改为模型?然后你向命令模型发送一个命令。在这个确切的场景中,您想要更改 Person 的名称。因此,您向聚合/命令模型发送命令。

在 AxonIQ 的网页上有一个架构概念部分,描述了所有主要原则。还有一个关于CQRS的内容可能会有所帮助。可能有助于阅读这些内容;很确定其中很多将解决您的很多问题。:-)

希望这可以帮助!


推荐阅读