Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 事件来源-将事件从AR传递给实体_Java_Events_Domain Driven Design_Cqrs_Event Sourcing - Fatal编程技术网

Java 事件来源-将事件从AR传递给实体

Java 事件来源-将事件从AR传递给实体,java,events,domain-driven-design,cqrs,event-sourcing,Java,Events,Domain Driven Design,Cqrs,Event Sourcing,我有一个更复杂的聚合根结构和事件源的问题。假设我有一段代码: class AggregateRoot{ Entity entity1; Entity entity2; //this is returned to service layer to be persisted to db in event stream AggregateRootUpdatedState execCommand(int command){ entity1 = new E

我有一个更复杂的聚合根结构和事件源的问题。假设我有一段代码:

class AggregateRoot{
    Entity entity1;
    Entity entity2;

    //this is returned to service layer to be persisted to db in event stream
    AggregateRootUpdatedState execCommand(int command){
        entity1 = new Entity();
        EntityUpdatedStateEvent event1 = this.entity1.changeState(command);

        EntityUpdatedStateEvent event2 = null;
        if(entity1.state==1) {  //since we already set sub entity - we can check this
            entity2 = new Entity();
            event2 = this.entity2.changeState(command);
        }

        AggregateRootUpdatedState parentEvent = new AggregateRootUpdatedState(event1, event2);
        //when(parentEvent);    //??? WE ALREADY CHANGED STATE IN TWO LINES ABOVE
        return parentEvent;
    }

    void when(AggregateRootUpdatedState event){ //needed for re-hydrating the event state
        entity1 = new Entity();
        entity1.when(event.event1);
        if(event.event2!=null) {
            entity2 = new Entity();
            entity2.when(event.event2);
        }
    }
}

class Entity{
    int state;

    EntityUpdatedStateEvent changeState(int state){
        EntityUpdatedStateEvent event = new EntityUpdatedStateEvent(state);
        when(event);
        return event;
    }

    void when(EntityUpdatedStateEvent event){
        this.state = event.state;
    }
}

class EntityUpdatedStateEvent{
    int state;

    EntityUpdatedStateEvent(int state) {
        this.state = state;
    }
}

class AggregateRootUpdatedState{
    EntityUpdatedStateEvent event1; //here we are nesting events AR->Entity
    EntityUpdatedStateEvent event2;

    AggregateRootUpdatedState(EntityUpdatedStateEvent event1, EntityUpdatedStateEvent event2) {
        this.event1 = event1;
        this.event2 = event2;
    }
}
如您所见,有一个聚合根
AggregateRoot
,它有两个子实体
entity1
entity2
。当AR接收到命令(在本例中为simple
int command
)时,它必须调用子实体上的一些方法,以便它们修改其状态。作为对此的反应,它们触发
EntityUpdatedStateEvent
,该事件通过调用
when
方法自动应用于实体内部。此时应用事件可以保证当实体返回时,聚合根将具有正确的状态集,并且我将能够在聚合根中执行比较测试
if(entity1.state==1)
。根据这个测试,我还更新了其他实体状态。然后,这两个事件被组合成
AggregateRootUpdatedState
事件,并保存到事件存储中

现在,我的问题是-在AR中,当第一次发生
AggregateRootUpdatedState
方法时(仅在重新水合AR时),我不会调用
。既然我看到AR状态也应该通过调用
when
方法来修改,那么这种方法正确吗

是否有其他方法将事件向下传递到AR层次结构

更新

class AggregateRoot{
    List<SubEntityLevel1> subEntityLevel1s;
    int rootNum;

    void command(int x){
        rootNum = x*x;
        for(int i=0; i<x; i++){
            SubEntityLevel1 subEntityLevel1 = new SubEntityLevel1();
            subEntityLevel1.modify1(i, rootNum);
            subEntityLevel1s.add(subEntityLevel1);
        }
    }

    void when(AggregateRootModifiedEvent event){
        //HOW TO REFACTOR METHOD ABOVE TO EVENT?
    }
}

class SubEntityLevel1{
    int id;
    List<SubEntityLevel2> subEntityLevel2s;
    int sum = 0;

    void modify1(int id, int rootNum){
        //HOW TO MAKE EVENT FROM THIS AND THEN APPLY IN WHEN() METHOD?
        this.id = id;
        this.sum = rootNum;
        for(int i=0; i<id; i++){
            if(subEntityLevel2s.stream().noneMatch(se2 -> "0".equals(se2.id))) {
                SubEntityLevel2 subEntityLevel2 = new SubEntityLevel2();
                subEntityLevel2.modify2(i);
                subEntityLevel2s.add(subEntityLevel2);
                sum++;
            }
        }
    }

    void when(SubEntityLevel1Modified event){
        this.id = event.id;
        this.sum = event.sum;
        for(SubEntityLevel2Modified subEvent : event.subEntity2Events){
            when(subEvent);
        }
    }

    void when(SubEntityLevel2Modified event){
        SubEntityLevel2 subEntityLevel2 = new SubEntityLevel2();
        subEntityLevel2.when(event);
        subEntityLevel2s.add(subEntityLevel2);
    }

    void when(SubEntityLevel2Created event){
        //??????
    }
}

class SubEntityLevel2{
    String id;

    SubEntityLevel2Modified modify2(int x){
        SubEntityLevel2Modified event = new SubEntityLevel2Modified(String.valueOf(x));
        when(event);
        return event;
    }

    void when(SubEntityLevel2Modified event){
        this.id = event.id;
    }
}

//----- EVENTS

class AggregateRootModifiedEvent{
    int rootNum;
    List<SubEntityLevel1Modified> subEntity1Events;

    public AggregateRootModifiedEvent(int rootNum, List<SubEntityLevel1Modified> subEntity1Events) {
        this.rootNum = rootNum;
        this.subEntity1Events = subEntity1Events;
    }
}

class SubEntityLevel1Modified{
    int id;
    List<SubEntityLevel2Modified> subEntity2Events;
    int sum;

    public SubEntityLevel1Modified(int id, List<SubEntityLevel2Modified> subEntity2Events, int sum) {
        this.id = id;
        this.subEntity2Events = subEntity2Events;
        this.sum = sum;
    }
}

class SubEntityLevel2Created{}

class SubEntityLevel2Modified{
    String id;

    SubEntityLevel2Modified(String id){
        this.id = id;
    }
}
然后将这两个事件组合成AggregateRootUpdatedState事件,并保存到事件存储中

在我看来,这是一种反模式;您可以让它在模型的版本1中工作,但当您想要开始重构或响应事件时,它会引入大量额外的工作。您可能应该考虑返回事件集合,而不是单个单一事件

您的聚合代码将如下所示

History execCommand(int command){
    entity1 = new Entity();
    EntityUpdatedStateEvent event1 = this.entity1.changeState(command);

    EntityUpdatedStateEvent event2 = null;
    if(entity1.state==1) {  //since we already set sub entity - we can check this
        entity2 = new Entity();
        event2 = this.entity2.changeState(command);
    }

    // ALL of the state changes have already happened, so no need to
    // re-process the events.
    return History.of(event1, event2)
}
另一件需要注意的事情是,在本例中,您一直在更改根实体而没有生成事件,特别是在创建子事件时

    entity1 = new Entity();
为什么实体生命周期的开始在您的模型中不是一件明确的事情?应该有这样一个事件,确保实体引用(this.entity1,this.entity2)总是以相同的方式分配

EntityOneCreatedEvent createEntityOne() {
    EntityOneCreatedEvent e = new EntityOneCreatedEvent();
    when(e);
    return e;
}
是否有其他方法将事件向下传递到AR层次结构

一种方法是使用Meyer模式,将创建事件的逻辑与更新实体状态的逻辑分开。 基本思想是,在查询中,您永远不会更改自己的状态(您可以复制您的状态,然后更改副本);在命令中,将更改应用于本地状态


如果您认为状态是一种不可变的值类型,那么这种模式真的会自然而然地从中产生。

谢谢您的回复。你能检查一下我更新的问题吗,因为它现在更真实地反映了我的问题。我同意我应该有这个CreatedEvent(但是在我上面的新问题中,我不知道以后如何引用它)。另外,正如您在第一个代码段中所回答的,在第一次执行时,最终聚合根不需要应用事件,仅在重新水合时。有没有梅耶模式与事件来源相关的例子?我会看一看——不过,作为一个一般性的提示:任何时候你询问DDD,你都应该尽可能接近你真正的问题。具有泛型约束的泛型域很难智能地建模。
EntityOneCreatedEvent createEntityOne() {
    EntityOneCreatedEvent e = new EntityOneCreatedEvent();
    when(e);
    return e;
}