@Override
@Transactional
public SaveUpdateResult save(String aggregateType, List<EventTypeAndData> events, Optional<AggregateCrudSaveOptions> saveOptions) {
List<EventIdTypeAndData> eventsWithIds = events.stream().map(this::toEventWithId).collect(Collectors.toList());
String entityId = saveOptions.flatMap(AggregateCrudSaveOptions::getEntityId).orElse(idGenerator.genId().asString());
Int128 entityVersion = last(eventsWithIds).getId();
try {
jdbcTemplate.update(String.format("INSERT INTO %s (entity_type, entity_id, entity_version) VALUES (?, ?, ?)", entityTable),
aggregateType, entityId, entityVersion.asString());
} catch (DuplicateKeyException e) {
throw new EntityAlreadyExistsException();
}
for (EventIdTypeAndData event : eventsWithIds)
jdbcTemplate.update(String.format("INSERT INTO %s (event_id, event_type, event_data, entity_type, entity_id, triggering_event, metadata) VALUES (?, ?, ?, ?, ?, ?, ?)", eventTable),
event.getId().asString(), event.getEventType(), event.getEventData(), aggregateType, entityId,
saveOptions.flatMap(AggregateCrudSaveOptions::getTriggeringEvent).map(EventContext::getEventToken).orElse(null),
event.getMetadata().orElse(null)
);
return new SaveUpdateResult(new EntityIdVersionAndEventIds(entityId, entityVersion, eventsWithIds.stream().map(EventIdTypeAndData::getId).collect(Collectors.toList())),
new PublishableEvents(aggregateType, entityId, eventsWithIds));
}