Reputation: 277
Cascade types don't seem to work with the entity manager that axon uses. If I use CascadeType.Persist, the second time I try to create an object with the same child I get a duplicate key constraint error. If I use CascadeType.Merge, it won't work if the entries do not exist in the database.
Tried using different CascadeTypes, also the hibernate @Cascade annotations but with no avail. Also tried to use @AggregateMember for the children but the children entities don't seem to be saved before the parent.
@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
}
}
Both Accessory and ExpeditionType are entities as well.
I am aware that we are not using the axon framework to it's full extent but by this point I'm just trying to get to save all the children entities before the OfficialRecordEntity properly - was expecting that the cascade type should suffice but due to axon's entity manager provider it doesn't seem to work that way.
Upvotes: 2
Views: 943
Reputation: 7275
Firstly, I would to point I am mostly in the habit of using the Event Sourced approach of storing and retrieving an Aggregate. Nonetheless, I have build a state-stored approach as well, which did include an Aggregate Root with several Aggregate Members under it, in a collection.
The following versions are of interest in deducing whether you have a similar set up as I have:
Then, my Aggregate and Entity looked something like this:
// 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...
}
This set up, without specifying the SomeAggregateRoot
Repository myself, works correctly for me. I thus let the axon-spring-boot-starter
dependency auto configure all the necessary Axon components.
I do know this isn't a direct answer to your question. I am however unsure where the issue lies in your set up, so I hope cross referencing your set up with what I just shared will give you an "a ha!" moment.
Update
To test this out with a shareable Github repository, I have set up one which shows the above in working condition, which you can find here.
Upvotes: 2