|
|
|
@ -27,6 +27,7 @@ import java.util.function.Function; |
|
|
|
import java.util.stream.Collectors; |
|
|
|
import java.util.stream.Collectors; |
|
|
|
import java.util.stream.StreamSupport; |
|
|
|
import java.util.stream.StreamSupport; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import org.jspecify.annotations.Nullable; |
|
|
|
import org.springframework.context.ApplicationContext; |
|
|
|
import org.springframework.context.ApplicationContext; |
|
|
|
import org.springframework.context.ApplicationEventPublisher; |
|
|
|
import org.springframework.context.ApplicationEventPublisher; |
|
|
|
import org.springframework.data.domain.Page; |
|
|
|
import org.springframework.data.domain.Page; |
|
|
|
@ -49,11 +50,22 @@ import org.springframework.data.relational.core.conversion.RootAggregateChange; |
|
|
|
import org.springframework.data.relational.core.mapping.RelationalMappingContext; |
|
|
|
import org.springframework.data.relational.core.mapping.RelationalMappingContext; |
|
|
|
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity; |
|
|
|
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity; |
|
|
|
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty; |
|
|
|
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty; |
|
|
|
import org.springframework.data.relational.core.mapping.event.*; |
|
|
|
import org.springframework.data.relational.core.mapping.event.AbstractRelationalEvent; |
|
|
|
|
|
|
|
import org.springframework.data.relational.core.mapping.event.AfterConvertCallback; |
|
|
|
|
|
|
|
import org.springframework.data.relational.core.mapping.event.AfterConvertEvent; |
|
|
|
|
|
|
|
import org.springframework.data.relational.core.mapping.event.AfterDeleteCallback; |
|
|
|
|
|
|
|
import org.springframework.data.relational.core.mapping.event.AfterDeleteEvent; |
|
|
|
|
|
|
|
import org.springframework.data.relational.core.mapping.event.AfterSaveCallback; |
|
|
|
|
|
|
|
import org.springframework.data.relational.core.mapping.event.AfterSaveEvent; |
|
|
|
|
|
|
|
import org.springframework.data.relational.core.mapping.event.BeforeConvertCallback; |
|
|
|
|
|
|
|
import org.springframework.data.relational.core.mapping.event.BeforeConvertEvent; |
|
|
|
|
|
|
|
import org.springframework.data.relational.core.mapping.event.BeforeDeleteCallback; |
|
|
|
|
|
|
|
import org.springframework.data.relational.core.mapping.event.BeforeDeleteEvent; |
|
|
|
|
|
|
|
import org.springframework.data.relational.core.mapping.event.BeforeSaveCallback; |
|
|
|
|
|
|
|
import org.springframework.data.relational.core.mapping.event.BeforeSaveEvent; |
|
|
|
|
|
|
|
import org.springframework.data.relational.core.mapping.event.Identifier; |
|
|
|
import org.springframework.data.relational.core.query.Query; |
|
|
|
import org.springframework.data.relational.core.query.Query; |
|
|
|
import org.springframework.data.support.PageableExecutionUtils; |
|
|
|
import org.springframework.data.support.PageableExecutionUtils; |
|
|
|
import org.springframework.data.util.Streamable; |
|
|
|
|
|
|
|
import org.springframework.lang.Nullable; |
|
|
|
|
|
|
|
import org.springframework.util.Assert; |
|
|
|
import org.springframework.util.Assert; |
|
|
|
import org.springframework.util.ClassUtils; |
|
|
|
import org.springframework.util.ClassUtils; |
|
|
|
|
|
|
|
|
|
|
|
@ -173,19 +185,7 @@ public class JdbcAggregateTemplate implements JdbcAggregateOperations { |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public <T> List<T> saveAll(Iterable<T> instances) { |
|
|
|
public <T> List<T> saveAll(Iterable<T> instances) { |
|
|
|
|
|
|
|
return saveInBatch(instances, instance -> changeCreatorSelectorForSave(instance)); |
|
|
|
Assert.notNull(instances, "Aggregate instances must not be null"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!instances.iterator().hasNext()) { |
|
|
|
|
|
|
|
return Collections.emptyList(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<EntityAndChangeCreator<T>> entityAndChangeCreators = new ArrayList<>(); |
|
|
|
|
|
|
|
for (T instance : instances) { |
|
|
|
|
|
|
|
verifyIdProperty(instance); |
|
|
|
|
|
|
|
entityAndChangeCreators.add(new EntityAndChangeCreator<>(instance, changeCreatorSelectorForSave(instance))); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return performSaveAll(entityAndChangeCreators); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
@ -206,21 +206,7 @@ public class JdbcAggregateTemplate implements JdbcAggregateOperations { |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public <T> List<T> insertAll(Iterable<T> instances) { |
|
|
|
public <T> List<T> insertAll(Iterable<T> instances) { |
|
|
|
|
|
|
|
return doInBatch(instances, entity -> createInsertChange(prepareVersionForInsert(entity))); |
|
|
|
Assert.notNull(instances, "Aggregate instances must not be null"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!instances.iterator().hasNext()) { |
|
|
|
|
|
|
|
return Collections.emptyList(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<EntityAndChangeCreator<T>> entityAndChangeCreators = new ArrayList<>(); |
|
|
|
|
|
|
|
for (T instance : instances) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Function<T, RootAggregateChange<T>> changeCreator = entity -> createInsertChange(prepareVersionForInsert(entity)); |
|
|
|
|
|
|
|
EntityAndChangeCreator<T> entityChange = new EntityAndChangeCreator<>(instance, changeCreator); |
|
|
|
|
|
|
|
entityAndChangeCreators.add(entityChange); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return performSaveAll(entityAndChangeCreators); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
@ -241,6 +227,10 @@ public class JdbcAggregateTemplate implements JdbcAggregateOperations { |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public <T> List<T> updateAll(Iterable<T> instances) { |
|
|
|
public <T> List<T> updateAll(Iterable<T> instances) { |
|
|
|
|
|
|
|
return doInBatch(instances, entity -> createUpdateChange(prepareVersionForUpdate(entity))); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private <T> List<T> saveInBatch(Iterable<T> instances, Function<T, AggregateChangeCreator<T>> changes) { |
|
|
|
|
|
|
|
|
|
|
|
Assert.notNull(instances, "Aggregate instances must not be null"); |
|
|
|
Assert.notNull(instances, "Aggregate instances must not be null"); |
|
|
|
|
|
|
|
|
|
|
|
@ -249,11 +239,27 @@ public class JdbcAggregateTemplate implements JdbcAggregateOperations { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
List<EntityAndChangeCreator<T>> entityAndChangeCreators = new ArrayList<>(); |
|
|
|
List<EntityAndChangeCreator<T>> entityAndChangeCreators = new ArrayList<>(); |
|
|
|
|
|
|
|
|
|
|
|
for (T instance : instances) { |
|
|
|
for (T instance : instances) { |
|
|
|
|
|
|
|
verifyIdProperty(instance); |
|
|
|
|
|
|
|
entityAndChangeCreators.add(new EntityAndChangeCreator<>(instance, changes.apply(instance))); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return performSaveAll(entityAndChangeCreators); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private <T> List<T> doInBatch(Iterable<T> instances, AggregateChangeCreator<T> changeCreatorFunction) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Assert.notNull(instances, "Aggregate instances must not be null"); |
|
|
|
|
|
|
|
|
|
|
|
Function<T, RootAggregateChange<T>> changeCreator = entity -> createUpdateChange(prepareVersionForUpdate(entity)); |
|
|
|
if (!instances.iterator().hasNext()) { |
|
|
|
EntityAndChangeCreator<T> entityChange = new EntityAndChangeCreator<>(instance, changeCreator); |
|
|
|
return Collections.emptyList(); |
|
|
|
entityAndChangeCreators.add(entityChange); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<EntityAndChangeCreator<T>> entityAndChangeCreators = new ArrayList<>(); |
|
|
|
|
|
|
|
for (T instance : instances) { |
|
|
|
|
|
|
|
verifyIdProperty(instance); |
|
|
|
|
|
|
|
entityAndChangeCreators.add(new EntityAndChangeCreator<T>(instance, changeCreatorFunction)); |
|
|
|
} |
|
|
|
} |
|
|
|
return performSaveAll(entityAndChangeCreators); |
|
|
|
return performSaveAll(entityAndChangeCreators); |
|
|
|
} |
|
|
|
} |
|
|
|
@ -473,7 +479,7 @@ public class JdbcAggregateTemplate implements JdbcAggregateOperations { |
|
|
|
|
|
|
|
|
|
|
|
T aggregateRoot = triggerBeforeConvert(instance.entity); |
|
|
|
T aggregateRoot = triggerBeforeConvert(instance.entity); |
|
|
|
|
|
|
|
|
|
|
|
RootAggregateChange<T> change = instance.changeCreator.apply(aggregateRoot); |
|
|
|
RootAggregateChange<T> change = instance.changeCreator.createAggregateChange(aggregateRoot); |
|
|
|
|
|
|
|
|
|
|
|
aggregateRoot = triggerBeforeSave(change.getRoot(), change); |
|
|
|
aggregateRoot = triggerBeforeSave(change.getRoot(), change); |
|
|
|
|
|
|
|
|
|
|
|
@ -531,7 +537,7 @@ public class JdbcAggregateTemplate implements JdbcAggregateOperations { |
|
|
|
return results; |
|
|
|
return results; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private <T> Function<T, RootAggregateChange<T>> changeCreatorSelectorForSave(T instance) { |
|
|
|
private <T> AggregateChangeCreator<T> changeCreatorSelectorForSave(T instance) { |
|
|
|
|
|
|
|
|
|
|
|
return context.getRequiredPersistentEntity(instance.getClass()).isNew(instance) |
|
|
|
return context.getRequiredPersistentEntity(instance.getClass()).isNew(instance) |
|
|
|
? entity -> createInsertChange(prepareVersionForInsert(entity)) |
|
|
|
? entity -> createInsertChange(prepareVersionForInsert(entity)) |
|
|
|
@ -671,6 +677,13 @@ public class JdbcAggregateTemplate implements JdbcAggregateOperations { |
|
|
|
private record EntityAndPreviousVersion<T> (T entity, @Nullable Number version) { |
|
|
|
private record EntityAndPreviousVersion<T> (T entity, @Nullable Number version) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private record EntityAndChangeCreator<T> (T entity, Function<T, RootAggregateChange<T>> changeCreator) { |
|
|
|
private record EntityAndChangeCreator<T> (T entity, AggregateChangeCreator<T> changeCreator) { |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private interface AggregateChangeCreator<T> extends Function<T, RootAggregateChange<T>> { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
default RootAggregateChange<T> createAggregateChange(T instance) { |
|
|
|
|
|
|
|
return this.apply(instance); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|