有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Axon聚合的唯一Id是否与实体的唯一Id相同?

我一定是做错了什么

我有一个非常简单的Axon应用程序,它有两个简单的功能:创建一个人&;更改此人的姓名

所以我有个人实体:

@Entity
@Data
@NoArgsConstructor
public class Person {    
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String name;
}

还有我的人物组合:

@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();
    }

}

这是我的changename命令:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class ChangeNameCommand {
    @TargetAggregateIdentifier
     private UUID id;
     private String name;    
}

这是我的名字ChangedEvent:

@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);
    }

}

共 (1) 个答案

  1. # 1 楼答案

    我觉得您仍然在将命令模型和查询模型的概念相互混合

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

    另一方面,查询模型只负责回答针对应用程序的问题。如果需要知道一个人的状态,这意味着您向一个组件发送一个查询,该组件能够返回您共享的Person实体

    回到你描述的“问题”:

    1. “这不是违背了事件来源的目的吗?一点真相?”:事件来源是一个特定于将命令模型事件本身中重新水化的概念。因此,使用事件源只是意味着不仅要确保通过事件创建查询模型,还要确保命令模型。因此,你这样做是在强制执行一个单一的真相来源。因此,使用事件来更新查询模型不会违背ES的目的
    2. “我们在这里传递哪个Id?聚合还是实体?”:当你有疑问时,试着找出你想要实现的目标。你在询问信息吗?然后是针对您的查询模型的查询。是否打算将某些状态更改为模型?然后向命令模型发送命令。在这种情况下,您需要更改一个人的名字。因此,可以向聚合/命令模型发送命令

    AxonIQ的网页上有一个Architectural Concepts部分描述了所有主要原则。还有一个关于CQRS的可能会有所帮助。 可能有助于了解这些;可以肯定的是,这些方法可以解决你的很多问题。:-)

    希望这有帮助