【问题标题】:Persisting ManyToOne/OneToOne relations in Axon aggregate在 Axon 聚合中保持 ManyToOne/OneToOne 关系
【发布时间】:2019-12-19 03:30:48
【问题描述】:

级联类型似乎不适用于 axon 使用的实体管理器。如果我使用 CascadeType.Persist,我第二次尝试使用同一个子对象创建一个对象时,会出现重复键约束错误。如果我使用 CascadeType.Merge,如果数据库中不存在条目,它将无法工作。

尝试使用不同的 CascadeTypes,以及休眠的 @Cascade 注释,但无济于事。还尝试将@AggregateMember 用于子级,但子级实体似乎没有在父级之前保存。

@Bean
Repository<OfficialRecordEntity> axonOfficialRecordRepository(EntityManagerProvider emp, ParameterResolverFactory parameterResolverFactory, EventBus eventBus) {
        return GenericJpaRepository.builder(OfficialRecordEntity.class)
                .parameterResolverFactory(parameterResolverFactory)
                .entityManagerProvider(emp)
                .eventBus(eventBus)
                .build();
}
@Aggregate
@Entity
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(of = {"id"}, callSuper = false)
@Builder
public class OfficialRecordEntity {
    @Id
    @AggregateIdentifier
    private String id;

    //many other fields

    @OneToMany(cascade = CascadeType.PERSIST)
    private List<Accessory> accessories;

    @ManyToOne(cascade = CascadeType.PERSIST)
    private ExpeditionType expeditionType;

    //many other commandhandlers/eventhandlers

    @CommandHandler
    public OfficialRecordEntity(CreateOfficialRecordCommand command) {
        apply(new CreateOfficialRecordEvent(command.getId(), command.getOfficialRecordDTO()));
    }

    @EventSourcingHandler
    public void on(final CreateOfficialRecordEvent event) {
        //...some field initializations    
    }
}

Accessory 和 ExpeditionType 也是实体。

我知道我们并没有完全使用轴突框架,但此时我只是试图在 OfficialRecordEntity 之前正确保存所有子实体 - 期望级联类型应该足够但由于对于 axon 的实体管理器提供者来说,它似乎不是那样工作的。

【问题讨论】:

    标签: java spring hibernate spring-boot axon


    【解决方案1】:

    首先,我要指出我主要习惯于使用事件源方法来存储和检索聚合。 尽管如此,我也构建了一个状态存储方法,它确实在一个集合中包含了一个聚合根,它下面有几个聚合成员。

    以下版本有助于推断您是否有与我类似的设置:

    • Java - 8
    • Axon 框架 - 4.1.1
    • Spring Boot(和 Starter Data JPA)- 2.0.5.RELEASE

    然后,我的聚合和实体看起来像这样:

    // Aggregate sample
    @Entity
    @Aggregate
    class SomeAggregateRoot {
    
        @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
        @JoinColumn(name = "entityId")
        @AggregateMember
        private List<SomeEntity> entities = new ArrayList<>();
    
        // Some command and event handlers...
    }
    
    
    // Aggregate Member sample
    @Entity
    public class SomeEntity {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private String id;
    
        @EntityId
        private String entityId;
    
        // Some command and event handlers...
    }
    

    这种设置,没有自己指定 SomeAggregateRoot 存储库,对我来说可以正常工作。因此,我让 axon-spring-boot-starter 依赖项自动配置所有必要的 Axon 组件。

    我知道这不是您问题的直接答案。 但是,我不确定问题出在您的设置中,所以我希望将您的设置与我刚刚分享的内容交叉引用会给您一个“哈哈!”时刻。


    更新

    为了使用可共享的 Github 存储库进行测试,我设置了一个在工作状态下显示上述内容的存储库,您可以找到 here

    【讨论】:

    • 交叉引用似乎是个好主意,我将尝试一下。谢谢!
    • 我尝试在一个小项目上执行此操作(也在我的精确用例中),但在这两种情况下,我都得到一个导致持久性异常的命令,当更新一个已经存在的子项时,分离实体传递给持久性在数据库中。在我看来,一旦子实体有一个 id,它就不会进行更新,因为调用了 persist() 方法:(。你怎么没有遇到同样的问题?:O
    • 在我的示例项目中,我确实使用了 H2 数据库,因为我真的不想为实际存储结果而烦恼。那么,也许这与您正在使用的数据库有关?
    • 我对 H2 数据库有完全相同的问题。我创建了一个快速项目来尝试您的解决方案(或此时的任何解决方案)。你能快速看一下吗?也许我做错了什么……github.com/Vlad-Olaru/axon-hibernate-tryout
    • 所以,我只是进行了广泛的查看,我得到的主要异常是org.hibernate.HibernateException: Unable to instantiate default tuplizer [org.hibernate.tuple.entity.PojoEntityTuplizer]。快速谷歌表明这是缺少构造函数的问题。补充说,我看到你正在使用 Lombok。这可能只会在某处导致不一致,所以我首先尝试在没有 Lombok 的情况下进行设置。最后,我看到您在命令/事件中添加了一个 Student 聚合成员。我强烈建议不要在您的消息中添加域模型。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多