Browse Source

DATAJDBC-291 - Polishing.

Introduce factory methods for AggregateChange save/delete object creation. Replace computeIfAbsent pattern with appropriate methods. Add indirection for staged values traversal. Rename CascadingValuesLookup to StagedValues.
Javadoc, formatting.

Original pull request: #173.
pull/170/head
Mark Paluch 6 years ago
parent
commit
1314081c52
No known key found for this signature in database
GPG Key ID: 51A00FA751B91849
  1. 12
      spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/JdbcAggregateTemplate.java
  2. 166
      spring-data-relational/src/main/java/org/springframework/data/relational/core/conversion/AggregateChange.java
  3. 7
      spring-data-relational/src/main/java/org/springframework/data/relational/core/conversion/DbAction.java
  4. 68
      spring-data-relational/src/test/java/org/springframework/data/relational/core/conversion/AggregateChangeIdGenerationImmutableUnitTests.java
  5. 42
      spring-data-relational/src/test/java/org/springframework/data/relational/core/conversion/AggregateChangeIdGenerationUnitTests.java

12
spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/JdbcAggregateTemplate.java

@ -26,7 +26,6 @@ import org.springframework.data.jdbc.core.convert.DataAccessStrategy; @@ -26,7 +26,6 @@ import org.springframework.data.jdbc.core.convert.DataAccessStrategy;
import org.springframework.data.mapping.IdentifierAccessor;
import org.springframework.data.mapping.callback.EntityCallbacks;
import org.springframework.data.relational.core.conversion.AggregateChange;
import org.springframework.data.relational.core.conversion.AggregateChange.Kind;
import org.springframework.data.relational.core.conversion.Interpreter;
import org.springframework.data.relational.core.conversion.RelationalConverter;
import org.springframework.data.relational.core.conversion.RelationalEntityDeleteWriter;
@ -331,33 +330,30 @@ public class JdbcAggregateTemplate implements JdbcAggregateOperations { @@ -331,33 +330,30 @@ public class JdbcAggregateTemplate implements JdbcAggregateOperations {
triggerAfterDelete(entity, id, change);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private <T> AggregateChange<T> createInsertChange(T instance) {
AggregateChange<T> aggregateChange = new AggregateChange(Kind.SAVE, instance.getClass(), instance);
AggregateChange<T> aggregateChange = AggregateChange.forSave(instance);
jdbcEntityInsertWriter.write(instance, aggregateChange);
return aggregateChange;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private <T> AggregateChange<T> createUpdateChange(T instance) {
AggregateChange<T> aggregateChange = new AggregateChange(Kind.SAVE, instance.getClass(), instance);
AggregateChange<T> aggregateChange = AggregateChange.forSave(instance);
jdbcEntityUpdateWriter.write(instance, aggregateChange);
return aggregateChange;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private <T> AggregateChange<T> createDeletingChange(Object id, @Nullable T entity, Class<T> domainType) {
AggregateChange<T> aggregateChange = new AggregateChange(Kind.DELETE, domainType, entity);
AggregateChange<T> aggregateChange = AggregateChange.forDelete(domainType, entity);
jdbcEntityDeleteWriter.write(id, aggregateChange);
return aggregateChange;
}
private AggregateChange<?> createDeletingChange(Class<?> domainType) {
AggregateChange<?> aggregateChange = new AggregateChange<>(Kind.DELETE, domainType, null);
AggregateChange<?> aggregateChange = AggregateChange.forDelete(domainType, null);
jdbcEntityDeleteWriter.write(null, aggregateChange);
return aggregateChange;
}

166
spring-data-relational/src/main/java/org/springframework/data/relational/core/conversion/AggregateChange.java

@ -25,6 +25,7 @@ import java.util.HashSet; @@ -25,6 +25,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.PersistentPropertyAccessor;
@ -34,6 +35,7 @@ import org.springframework.data.relational.core.mapping.RelationalPersistentEnti @@ -34,6 +35,7 @@ import org.springframework.data.relational.core.mapping.RelationalPersistentEnti
import org.springframework.data.util.Pair;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/**
* Represents the change happening to the aggregate (as used in the context of Domain Driven Design) as a whole.
@ -59,7 +61,53 @@ public class AggregateChange<T> { @@ -59,7 +61,53 @@ public class AggregateChange<T> {
this.entity = entity;
}
/**
* Factory method to create an {@link AggregateChange} for saving entities.
*
* @param entity aggregate root to save.
* @param <T> entity type.
* @return the {@link AggregateChange} for saving the root {@code entity}.
* @since 1.2
*/
@SuppressWarnings("unchecked")
public static <T> AggregateChange<T> forSave(T entity) {
Assert.notNull(entity, "Entity must not be null");
return new AggregateChange<>(Kind.SAVE, (Class<T>) ClassUtils.getUserClass(entity), entity);
}
/**
* Factory method to create an {@link AggregateChange} for deleting entities.
*
* @param entity aggregate root to delete.
* @param <T> entity type.
* @return the {@link AggregateChange} for deleting the root {@code entity}.
* @since 1.2
*/
@SuppressWarnings("unchecked")
public static <T> AggregateChange<T> forDelete(T entity) {
Assert.notNull(entity, "Entity must not be null");
return forDelete((Class<T>) ClassUtils.getUserClass(entity), entity);
}
/**
* Factory method to create an {@link AggregateChange} for deleting entities.
*
* @param entityClass aggregate root type.
* @param entity aggregate root to delete.
* @param <T> entity type.
* @return the {@link AggregateChange} for deleting the root {@code entity}.
* @since 1.2
*/
public static <T> AggregateChange<T> forDelete(Class<T> entityClass, @Nullable T entity) {
Assert.notNull(entityClass, "Entity class must not be null");
return new AggregateChange<>(Kind.DELETE, entityClass, entity);
}
public void setEntity(@Nullable T aggregateRoot) {
// TODO: Check instanceOf compatibility to ensure type contract.
entity = aggregateRoot;
}
@ -67,16 +115,15 @@ public class AggregateChange<T> { @@ -67,16 +115,15 @@ public class AggregateChange<T> {
actions.forEach(action -> action.executeWith(interpreter));
T newRoot = setGeneratedIds(context, converter);
T newRoot = populateIdsIfNecessary(context, converter);
if (newRoot != null) {
entity = newRoot;
}
}
@SuppressWarnings("unchecked")
@Nullable
private T setGeneratedIds(RelationalMappingContext context, RelationalConverter converter) {
private T populateIdsIfNecessary(RelationalMappingContext context, RelationalConverter converter) {
T newRoot = null;
@ -84,32 +131,31 @@ public class AggregateChange<T> { @@ -84,32 +131,31 @@ public class AggregateChange<T> {
ArrayList<DbAction<?>> reverseActions = new ArrayList<>(actions);
Collections.reverse(reverseActions);
CascadingValuesLookup cascadingValues = new CascadingValuesLookup();
StagedValues cascadingValues = new StagedValues();
for (DbAction<?> action : reverseActions) {
if (action instanceof DbAction.WithGeneratedId) {
DbAction.WithGeneratedId<?> withGeneratedId = (DbAction.WithGeneratedId<?>) action;
Object generatedId = withGeneratedId.getGeneratedId();
if (!(action instanceof DbAction.WithGeneratedId)) {
continue;
}
Object newEntity = setIdAndCascadingProperties(context, converter, withGeneratedId, generatedId,
cascadingValues);
DbAction.WithGeneratedId<?> withGeneratedId = (DbAction.WithGeneratedId<?>) action;
Object generatedId = withGeneratedId.getGeneratedId();
Object newEntity = setIdAndCascadingProperties(context, converter, withGeneratedId, generatedId, cascadingValues);
// the id property was immutable so we have to propagate changes up the tree
if (newEntity != ((DbAction.WithGeneratedId<?>) action).getEntity()) {
// the id property was immutable so we have to propagate changes up the tree
if (newEntity != ((DbAction.WithGeneratedId<?>) action).getEntity()) {
if (action instanceof DbAction.Insert) {
DbAction.Insert insert = (DbAction.Insert) action;
if (action instanceof DbAction.Insert) {
DbAction.Insert insert = (DbAction.Insert) action;
Pair qualifier = insert.getQualifier();
Pair qualifier = insert.getQualifier();
cascadingValues.add(insert.dependingOn, insert.propertyPath, newEntity,
qualifier == null ? null : qualifier.getSecond());
cascadingValues.stage(insert.dependingOn, insert.propertyPath,
qualifier == null ? null : qualifier.getSecond(), newEntity);
} else if (action instanceof DbAction.InsertRoot) {
newRoot = (T) newEntity;
}
} else if (action instanceof DbAction.InsertRoot) {
newRoot = entityType.cast(newEntity);
}
}
}
@ -119,7 +165,7 @@ public class AggregateChange<T> { @@ -119,7 +165,7 @@ public class AggregateChange<T> {
@SuppressWarnings("unchecked")
private <S> Object setIdAndCascadingProperties(RelationalMappingContext context, RelationalConverter converter,
DbAction.WithGeneratedId<S> action, @Nullable Object generatedId, CascadingValuesLookup cascadingValues) {
DbAction.WithGeneratedId<S> action, @Nullable Object generatedId, StagedValues cascadingValues) {
S originalEntity = action.getEntity();
@ -132,19 +178,14 @@ public class AggregateChange<T> { @@ -132,19 +178,14 @@ public class AggregateChange<T> {
}
// set values of changed immutables referenced by this entity
Map<PersistentPropertyPath, Object> cascadingValue = cascadingValues.get(action);
for (Map.Entry<PersistentPropertyPath, Object> pathValuePair : cascadingValue.entrySet()) {
propertyAccessor.setProperty(getRelativePath(action, pathValuePair), pathValuePair.getValue());
}
cascadingValues.forEachPath(action, (persistentPropertyPath, o) -> propertyAccessor
.setProperty(getRelativePath(action, persistentPropertyPath), o));
return propertyAccessor.getBean();
}
@SuppressWarnings("unchecked")
private PersistentPropertyPath getRelativePath(DbAction action,
Map.Entry<PersistentPropertyPath, Object> pathValuePair) {
PersistentPropertyPath pathToValue = pathValuePair.getKey();
private PersistentPropertyPath getRelativePath(DbAction action, PersistentPropertyPath pathToValue) {
if (action instanceof DbAction.Insert) {
return pathToValue.getExtensionForBaseOf(((DbAction.Insert) action).propertyPath);
@ -178,12 +219,13 @@ public class AggregateChange<T> { @@ -178,12 +219,13 @@ public class AggregateChange<T> {
}
/**
* Gathers and holds information about immutable properties in an aggregate that need updating.
* Accumulates information about staged immutable objects in an aggregate that require updating because their state
* changed because of {@link DbAction} execution.
*/
private static class CascadingValuesLookup {
private static class StagedValues {
static final List<MultiValueAggregator> aggregators = Arrays.asList(new SetAggregator(), new MapAggregator(),
new ListAggregator(), new SingleElementAggregator());
static final List<MultiValueAggregator> aggregators = Arrays.asList(SetAggregator.INSTANCE, MapAggregator.INSTANCE,
ListAggregator.INSTANCE, SingleElementAggregator.INSTANCE);
Map<DbAction, Map<PersistentPropertyPath, Object>> values = new HashMap<>();
@ -194,27 +236,22 @@ public class AggregateChange<T> { @@ -194,27 +236,22 @@ public class AggregateChange<T> {
* @param action The action responsible for persisting the entity that needs the added value set. Must not be
* {@literal null}.
* @param path The path to the property in which to set the value. Must not be {@literal null}.
* @param value The value to be set. Must not be {@literal null}.
* @param qualifier If {@code path} is a qualified multivalued properties this parameter contains the qualifier. May
* be {@literal null}.
* @param value The value to be set. Must not be {@literal null}.
*/
@SuppressWarnings("unchecked")
public <T> void add(DbAction<?> action, PersistentPropertyPath path, Object value, @Nullable Object qualifier) {
<T> void stage(DbAction<?> action, PersistentPropertyPath path, @Nullable Object qualifier, Object value) {
MultiValueAggregator<T> aggregator = getAggregatorFor(path);
Map<PersistentPropertyPath, Object> valuesForPath = this.values.get(action);
if (valuesForPath == null) {
valuesForPath = new HashMap<>();
values.put(action, valuesForPath);
}
Map<PersistentPropertyPath, Object> valuesForPath = this.values.computeIfAbsent(action,
dbAction -> new HashMap<>());
T currentValue = (T) valuesForPath.get(path);
if (currentValue == null) {
currentValue = aggregator.createEmptyInstance();
}
T currentValue = (T) valuesForPath.computeIfAbsent(path,
persistentPropertyPath -> aggregator.createEmptyInstance());
Object newValue = aggregator.add(currentValue, value, qualifier);
Object newValue = aggregator.add(currentValue, qualifier, value);
valuesForPath.put(path, newValue);
}
@ -231,8 +268,17 @@ public class AggregateChange<T> { @@ -231,8 +268,17 @@ public class AggregateChange<T> {
throw new IllegalStateException(String.format("Can't handle path %s", path));
}
public Map<PersistentPropertyPath, Object> get(DbAction<?> action) {
return values.getOrDefault(action, Collections.emptyMap());
/**
* Performs the given action for each entry in this the staging area that are provided by {@link DbAction} until all
* {@link PersistentPropertyPath} have been processed or the action throws an exception. The {@link BiConsumer
* action} is called with each applicable {@link PersistentPropertyPath} and {@code value} that is assignable to the
* property.
*
* @param dbAction
* @param action
*/
void forEachPath(DbAction<?> dbAction, BiConsumer<PersistentPropertyPath, Object> action) {
values.getOrDefault(dbAction, Collections.emptyMap()).forEach(action);
}
}
@ -249,11 +295,13 @@ public class AggregateChange<T> { @@ -249,11 +295,13 @@ public class AggregateChange<T> {
@Nullable
T createEmptyInstance();
T add(@Nullable T aggregate, Object value, @Nullable Object qualifier);
T add(@Nullable T aggregate, @Nullable Object qualifier, Object value);
}
static private class SetAggregator implements MultiValueAggregator<Set> {
private enum SetAggregator implements MultiValueAggregator<Set> {
INSTANCE;
@Override
public Class<Set> handledType() {
@ -267,7 +315,7 @@ public class AggregateChange<T> { @@ -267,7 +315,7 @@ public class AggregateChange<T> {
@SuppressWarnings("unchecked")
@Override
public Set add(@Nullable Set set, Object value, @Nullable Object qualifier) {
public Set add(@Nullable Set set, @Nullable Object qualifier, Object value) {
Assert.notNull(set, "Set must not be null");
@ -276,7 +324,9 @@ public class AggregateChange<T> { @@ -276,7 +324,9 @@ public class AggregateChange<T> {
}
}
static private class ListAggregator implements MultiValueAggregator<List> {
private enum ListAggregator implements MultiValueAggregator<List> {
INSTANCE;
@Override
public boolean handles(PersistentProperty property) {
@ -290,7 +340,7 @@ public class AggregateChange<T> { @@ -290,7 +340,7 @@ public class AggregateChange<T> {
@SuppressWarnings("unchecked")
@Override
public List add(@Nullable List list, Object value, @Nullable Object qualifier) {
public List add(@Nullable List list, @Nullable Object qualifier, Object value) {
Assert.notNull(list, "List must not be null.");
@ -305,7 +355,9 @@ public class AggregateChange<T> { @@ -305,7 +355,9 @@ public class AggregateChange<T> {
}
}
static private class MapAggregator implements MultiValueAggregator<Map> {
private enum MapAggregator implements MultiValueAggregator<Map> {
INSTANCE;
@Override
public Class<Map> handledType() {
@ -319,7 +371,7 @@ public class AggregateChange<T> { @@ -319,7 +371,7 @@ public class AggregateChange<T> {
@SuppressWarnings("unchecked")
@Override
public Map add(@Nullable Map map, Object value, @Nullable Object qualifier) {
public Map add(@Nullable Map map, @Nullable Object qualifier, Object value) {
Assert.notNull(map, "Map must not be null.");
@ -328,7 +380,9 @@ public class AggregateChange<T> { @@ -328,7 +380,9 @@ public class AggregateChange<T> {
}
}
static private class SingleElementAggregator implements MultiValueAggregator<Object> {
private enum SingleElementAggregator implements MultiValueAggregator<Object> {
INSTANCE;
@Override
@Nullable
@ -337,7 +391,7 @@ public class AggregateChange<T> { @@ -337,7 +391,7 @@ public class AggregateChange<T> {
}
@Override
public Object add(@Nullable Object __null, Object value, @Nullable Object qualifier) {
public Object add(@Nullable Object __null, @Nullable Object qualifier, Object value) {
return value;
}
}

7
spring-data-relational/src/main/java/org/springframework/data/relational/core/conversion/DbAction.java

@ -262,6 +262,9 @@ public interface DbAction<T> { @@ -262,6 +262,9 @@ public interface DbAction<T> {
*/
Map<PersistentPropertyPath<RelationalPersistentProperty>, Object> getQualifiers();
// TODO: Encapsulate propertyPath and qualifier in object: PropertyPathWithListIndex,
// PropertyPathWithMapIndex, PropertyPathInSet, PropertyPathWithoutQualifier
// Probably we need better names.
@Nullable
default Pair<PersistentPropertyPath<RelationalPersistentProperty>, Object> getQualifier() {
Map<PersistentPropertyPath<RelationalPersistentProperty>, Object> qualifiers = getQualifiers();
@ -272,14 +275,14 @@ public interface DbAction<T> { @@ -272,14 +275,14 @@ public interface DbAction<T> {
throw new IllegalStateException("Can't handle more then on qualifier");
}
Map.Entry<PersistentPropertyPath<RelationalPersistentProperty>, Object> entry = qualifiers.entrySet().iterator().next();
Map.Entry<PersistentPropertyPath<RelationalPersistentProperty>, Object> entry = qualifiers.entrySet().iterator()
.next();
if (entry.getValue() == null) {
return null;
}
return Pair.of(entry.getKey(), entry.getValue());
};
@Override
default Class<T> getEntityType() {
return WithEntity.super.getEntityType();

68
spring-data-relational/src/test/java/org/springframework/data/relational/core/conversion/AggregateChangeIdGenerationImmutableUnitTests.java

@ -18,6 +18,7 @@ package org.springframework.data.relational.core.conversion; @@ -18,6 +18,7 @@ package org.springframework.data.relational.core.conversion;
import static java.util.Arrays.*;
import static java.util.Collections.*;
import static org.assertj.core.api.Assertions.*;
import static org.assertj.core.api.SoftAssertions.*;
import lombok.AllArgsConstructor;
import lombok.Value;
@ -30,8 +31,8 @@ import java.util.Set; @@ -30,8 +31,8 @@ import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.assertj.core.api.SoftAssertions;
import org.junit.Test;
import org.springframework.data.annotation.Id;
import org.springframework.data.mapping.PersistentPropertyPath;
import org.springframework.data.mapping.PersistentPropertyPaths;
@ -41,7 +42,8 @@ import org.springframework.data.relational.core.mapping.RelationalPersistentProp @@ -41,7 +42,8 @@ import org.springframework.data.relational.core.mapping.RelationalPersistentProp
import org.springframework.lang.Nullable;
/**
* Unit tests for the {@link AggregateChange} testing the setting of generated ids in aggregates consisting of immutable entities.
* Unit tests for the {@link AggregateChange} testing the setting of generated ids in aggregates consisting of immutable
* entities.
*
* @author Jens Schauder
* @author Myeonghyeon-Lee
@ -59,14 +61,12 @@ public class AggregateChangeIdGenerationImmutableUnitTests { @@ -59,14 +61,12 @@ public class AggregateChangeIdGenerationImmutableUnitTests {
RelationalMappingContext context = new RelationalMappingContext();
RelationalConverter converter = new BasicRelationalConverter(context);
DbAction.WithEntity<?> rootInsert = new DbAction.InsertRoot<>(entity);
@Test // DATAJDBC-291
public void singleRoot() {
AggregateChange<DummyEntity> aggregateChange = new AggregateChange<>(AggregateChange.Kind.SAVE, DummyEntity.class,
entity);
AggregateChange<DummyEntity> aggregateChange = AggregateChange.forSave(entity);
aggregateChange.addAction(rootInsert);
aggregateChange.executeWith(new IdSettingInterpreter(), context, converter);
@ -81,8 +81,7 @@ public class AggregateChangeIdGenerationImmutableUnitTests { @@ -81,8 +81,7 @@ public class AggregateChangeIdGenerationImmutableUnitTests {
entity = entity.withSingle(content);
AggregateChange<DummyEntity> aggregateChange = new AggregateChange<>(AggregateChange.Kind.SAVE, DummyEntity.class,
entity);
AggregateChange<DummyEntity> aggregateChange = AggregateChange.forSave(entity);
aggregateChange.addAction(rootInsert);
aggregateChange.addAction(createInsert("single", content, null));
@ -90,7 +89,7 @@ public class AggregateChangeIdGenerationImmutableUnitTests { @@ -90,7 +89,7 @@ public class AggregateChangeIdGenerationImmutableUnitTests {
entity = aggregateChange.getEntity();
SoftAssertions.assertSoftly(softly -> {
assertSoftly(softly -> {
softly.assertThat(entity.rootId).isEqualTo(1);
softly.assertThat(entity.single.id).isEqualTo(2);
@ -102,8 +101,7 @@ public class AggregateChangeIdGenerationImmutableUnitTests { @@ -102,8 +101,7 @@ public class AggregateChangeIdGenerationImmutableUnitTests {
entity = entity.withContentList(asList(content, content2));
AggregateChange<DummyEntity> aggregateChange = new AggregateChange<>(AggregateChange.Kind.SAVE, DummyEntity.class,
entity);
AggregateChange<DummyEntity> aggregateChange = AggregateChange.forSave(entity);
aggregateChange.addAction(rootInsert);
aggregateChange.addAction(createInsert("contentList", content, 0));
aggregateChange.addAction(createInsert("contentList", content2, 1));
@ -112,7 +110,7 @@ public class AggregateChangeIdGenerationImmutableUnitTests { @@ -112,7 +110,7 @@ public class AggregateChangeIdGenerationImmutableUnitTests {
entity = aggregateChange.getEntity();
SoftAssertions.assertSoftly(softly -> {
assertSoftly(softly -> {
softly.assertThat(entity.rootId).isEqualTo(1);
softly.assertThat(entity.contentList).extracting(c -> c.id).containsExactly(2, 3);
@ -124,8 +122,7 @@ public class AggregateChangeIdGenerationImmutableUnitTests { @@ -124,8 +122,7 @@ public class AggregateChangeIdGenerationImmutableUnitTests {
entity = entity.withContentMap(createContentMap("a", content, "b", content2));
AggregateChange<DummyEntity> aggregateChange = new AggregateChange<>(AggregateChange.Kind.SAVE, DummyEntity.class,
entity);
AggregateChange<DummyEntity> aggregateChange = AggregateChange.forSave(entity);
aggregateChange.addAction(rootInsert);
aggregateChange.addAction(createInsert("contentMap", content, "a"));
aggregateChange.addAction(createInsert("contentMap", content2, "b"));
@ -147,8 +144,7 @@ public class AggregateChangeIdGenerationImmutableUnitTests { @@ -147,8 +144,7 @@ public class AggregateChangeIdGenerationImmutableUnitTests {
DbAction.Insert<?> parentInsert = createInsert("single", content, null);
DbAction.Insert<?> insert = createDeepInsert("single", tag1, null, parentInsert);
AggregateChange<DummyEntity> aggregateChange = new AggregateChange<>(AggregateChange.Kind.SAVE, DummyEntity.class,
entity);
AggregateChange<DummyEntity> aggregateChange = AggregateChange.forSave(entity);
aggregateChange.addAction(rootInsert);
aggregateChange.addAction(parentInsert);
aggregateChange.addAction(insert);
@ -172,8 +168,7 @@ public class AggregateChangeIdGenerationImmutableUnitTests { @@ -172,8 +168,7 @@ public class AggregateChangeIdGenerationImmutableUnitTests {
DbAction.Insert<?> insert1 = createDeepInsert("tagList", tag1, 0, parentInsert);
DbAction.Insert<?> insert2 = createDeepInsert("tagList", tag2, 1, parentInsert);
AggregateChange<DummyEntity> aggregateChange = new AggregateChange<>(AggregateChange.Kind.SAVE, DummyEntity.class,
entity);
AggregateChange<DummyEntity> aggregateChange = AggregateChange.forSave(entity);
aggregateChange.addAction(rootInsert);
aggregateChange.addAction(parentInsert);
aggregateChange.addAction(insert1);
@ -183,7 +178,7 @@ public class AggregateChangeIdGenerationImmutableUnitTests { @@ -183,7 +178,7 @@ public class AggregateChangeIdGenerationImmutableUnitTests {
entity = aggregateChange.getEntity();
SoftAssertions.assertSoftly(softly -> {
assertSoftly(softly -> {
softly.assertThat(entity.rootId).isEqualTo(1);
softly.assertThat(entity.single.id).isEqualTo(2);
@ -201,8 +196,7 @@ public class AggregateChangeIdGenerationImmutableUnitTests { @@ -201,8 +196,7 @@ public class AggregateChangeIdGenerationImmutableUnitTests {
DbAction.Insert<?> insert1 = createDeepInsert("tagSet", tag1, null, parentInsert);
DbAction.Insert<?> insert2 = createDeepInsert("tagSet", tag2, null, parentInsert);
AggregateChange<DummyEntity> aggregateChange = new AggregateChange<>(AggregateChange.Kind.SAVE, DummyEntity.class,
entity);
AggregateChange<DummyEntity> aggregateChange = AggregateChange.forSave(entity);
aggregateChange.addAction(rootInsert);
aggregateChange.addAction(parentInsert);
aggregateChange.addAction(insert1);
@ -212,7 +206,7 @@ public class AggregateChangeIdGenerationImmutableUnitTests { @@ -212,7 +206,7 @@ public class AggregateChangeIdGenerationImmutableUnitTests {
entity = aggregateChange.getEntity();
SoftAssertions.assertSoftly(softly -> {
assertSoftly(softly -> {
softly.assertThat(entity.rootId).isEqualTo(1);
softly.assertThat(entity.contentSet) //
@ -237,8 +231,7 @@ public class AggregateChangeIdGenerationImmutableUnitTests { @@ -237,8 +231,7 @@ public class AggregateChangeIdGenerationImmutableUnitTests {
DbAction.Insert<?> insert1 = createDeepInsert("single", tag1, null, parentInsert1);
DbAction.Insert<?> insert2 = createDeepInsert("single", tag2, null, parentInsert2);
AggregateChange<DummyEntity> aggregateChange = new AggregateChange<>(AggregateChange.Kind.SAVE, DummyEntity.class,
entity);
AggregateChange<DummyEntity> aggregateChange = AggregateChange.forSave(entity);
aggregateChange.addAction(rootInsert);
aggregateChange.addAction(parentInsert1);
aggregateChange.addAction(parentInsert2);
@ -249,7 +242,7 @@ public class AggregateChangeIdGenerationImmutableUnitTests { @@ -249,7 +242,7 @@ public class AggregateChangeIdGenerationImmutableUnitTests {
entity = aggregateChange.getEntity();
SoftAssertions.assertSoftly(softly -> {
assertSoftly(softly -> {
softly.assertThat(entity.rootId).isEqualTo(1);
softly.assertThat(entity.contentList) //
@ -271,8 +264,7 @@ public class AggregateChangeIdGenerationImmutableUnitTests { @@ -271,8 +264,7 @@ public class AggregateChangeIdGenerationImmutableUnitTests {
DbAction.Insert<?> insert2 = createDeepInsert("tagList", tag2, 0, parentInsert2);
DbAction.Insert<?> insert3 = createDeepInsert("tagList", tag3, 1, parentInsert2);
AggregateChange<DummyEntity> aggregateChange = new AggregateChange<>(AggregateChange.Kind.SAVE, DummyEntity.class,
entity);
AggregateChange<DummyEntity> aggregateChange = AggregateChange.forSave(entity);
aggregateChange.addAction(rootInsert);
aggregateChange.addAction(parentInsert1);
aggregateChange.addAction(parentInsert2);
@ -284,7 +276,7 @@ public class AggregateChangeIdGenerationImmutableUnitTests { @@ -284,7 +276,7 @@ public class AggregateChangeIdGenerationImmutableUnitTests {
entity = aggregateChange.getEntity();
SoftAssertions.assertSoftly(softly -> {
assertSoftly(softly -> {
softly.assertThat(entity.rootId).isEqualTo(1);
softly.assertThat(entity.contentList) //
@ -309,8 +301,7 @@ public class AggregateChangeIdGenerationImmutableUnitTests { @@ -309,8 +301,7 @@ public class AggregateChangeIdGenerationImmutableUnitTests {
DbAction.Insert<?> insert2 = createDeepInsert("tagMap", tag2, "222", parentInsert2);
DbAction.Insert<?> insert3 = createDeepInsert("tagMap", tag3, "333", parentInsert2);
AggregateChange<DummyEntity> aggregateChange = new AggregateChange<>(AggregateChange.Kind.SAVE, DummyEntity.class,
entity);
AggregateChange<DummyEntity> aggregateChange = AggregateChange.forSave(entity);
aggregateChange.addAction(rootInsert);
aggregateChange.addAction(parentInsert1);
aggregateChange.addAction(parentInsert2);
@ -322,7 +313,7 @@ public class AggregateChangeIdGenerationImmutableUnitTests { @@ -322,7 +313,7 @@ public class AggregateChangeIdGenerationImmutableUnitTests {
entity = aggregateChange.getEntity();
SoftAssertions.assertSoftly(softly -> {
assertSoftly(softly -> {
softly.assertThat(entity.rootId).isEqualTo(1);
softly.assertThat(entity.contentMap.entrySet()) //
@ -351,8 +342,7 @@ public class AggregateChangeIdGenerationImmutableUnitTests { @@ -351,8 +342,7 @@ public class AggregateChangeIdGenerationImmutableUnitTests {
DbAction.Insert<?> insert1 = createDeepInsert("single", tag1, null, parentInsert1);
DbAction.Insert<?> insert2 = createDeepInsert("single", tag2, null, parentInsert2);
AggregateChange<DummyEntity> aggregateChange = new AggregateChange<>(AggregateChange.Kind.SAVE, DummyEntity.class,
entity);
AggregateChange<DummyEntity> aggregateChange = AggregateChange.forSave(entity);
aggregateChange.addAction(rootInsert);
aggregateChange.addAction(parentInsert1);
aggregateChange.addAction(parentInsert2);
@ -363,7 +353,7 @@ public class AggregateChangeIdGenerationImmutableUnitTests { @@ -363,7 +353,7 @@ public class AggregateChangeIdGenerationImmutableUnitTests {
entity = aggregateChange.getEntity();
SoftAssertions.assertSoftly(softly -> {
assertSoftly(softly -> {
softly.assertThat(entity.rootId).isEqualTo(1);
softly.assertThat(entity.contentNoIdList) //
@ -380,8 +370,7 @@ public class AggregateChangeIdGenerationImmutableUnitTests { @@ -380,8 +370,7 @@ public class AggregateChangeIdGenerationImmutableUnitTests {
DbAction.Insert<?> parentInsert = createInsert("embedded.single", tag1, null);
AggregateChange<DummyEntity> aggregateChange = new AggregateChange<>(AggregateChange.Kind.SAVE, DummyEntity.class,
entity);
AggregateChange<DummyEntity> aggregateChange = AggregateChange.forSave(entity);
aggregateChange.addAction(rootInsert);
aggregateChange.addAction(parentInsert);
@ -441,11 +430,10 @@ public class AggregateChangeIdGenerationImmutableUnitTests { @@ -441,11 +430,10 @@ public class AggregateChangeIdGenerationImmutableUnitTests {
PersistentPropertyPath<RelationalPersistentProperty> toPath(DummyEntity root, Object pathValue) {
// DefaultPersistentPropertyPath is package-public
return new WritingContext(context, entity,
new AggregateChange<>(AggregateChange.Kind.SAVE, DummyEntity.class, root)).insert().stream()
.filter(a -> a instanceof DbAction.Insert).map(DbAction.Insert.class::cast)
.filter(a -> a.getEntity() == pathValue).map(DbAction.Insert::getPropertyPath).findFirst()
.orElseThrow(() -> new IllegalArgumentException("No matching path found for " + pathValue));
return new WritingContext(context, entity, AggregateChange.forSave(root)).insert().stream()
.filter(a -> a instanceof DbAction.Insert).map(DbAction.Insert.class::cast)
.filter(a -> a.getEntity() == pathValue).map(DbAction.Insert::getPropertyPath).findFirst()
.orElseThrow(() -> new IllegalArgumentException("No matching path found for " + pathValue));
}
@Value

42
spring-data-relational/src/test/java/org/springframework/data/relational/core/conversion/AggregateChangeIdGenerationUnitTests.java

@ -37,7 +37,7 @@ import org.springframework.lang.Nullable; @@ -37,7 +37,7 @@ import org.springframework.lang.Nullable;
* Unit tests for the {@link AggregateChange}.
*
* @author Jens Schauder
* Myeonghyeon-Lee
* @author Myeonghyeon-Lee
*/
public class AggregateChangeIdGenerationUnitTests {
@ -50,14 +50,12 @@ public class AggregateChangeIdGenerationUnitTests { @@ -50,14 +50,12 @@ public class AggregateChangeIdGenerationUnitTests {
RelationalMappingContext context = new RelationalMappingContext();
RelationalConverter converter = new BasicRelationalConverter(context);
DbAction.WithEntity<?> rootInsert = new DbAction.InsertRoot<>(entity);
@Test // DATAJDBC-291
public void singleRoot() {
AggregateChange<DummyEntity> aggregateChange = new AggregateChange<>(AggregateChange.Kind.SAVE, DummyEntity.class,
entity);
AggregateChange<DummyEntity> aggregateChange = AggregateChange.forSave(entity);
aggregateChange.addAction(rootInsert);
aggregateChange.executeWith(new IdSettingInterpreter(), context, converter);
@ -70,8 +68,7 @@ public class AggregateChangeIdGenerationUnitTests { @@ -70,8 +68,7 @@ public class AggregateChangeIdGenerationUnitTests {
entity.single = content;
AggregateChange<DummyEntity> aggregateChange = new AggregateChange<>(AggregateChange.Kind.SAVE, DummyEntity.class,
entity);
AggregateChange<DummyEntity> aggregateChange = AggregateChange.forSave(entity);
aggregateChange.addAction(rootInsert);
aggregateChange.addAction(createInsert("single", content, null));
@ -90,8 +87,7 @@ public class AggregateChangeIdGenerationUnitTests { @@ -90,8 +87,7 @@ public class AggregateChangeIdGenerationUnitTests {
entity.contentList.add(content);
entity.contentList.add(content2);
AggregateChange<DummyEntity> aggregateChange = new AggregateChange<>(AggregateChange.Kind.SAVE, DummyEntity.class,
entity);
AggregateChange<DummyEntity> aggregateChange = AggregateChange.forSave(entity);
aggregateChange.addAction(rootInsert);
aggregateChange.addAction(createInsert("contentList", content, 0));
aggregateChange.addAction(createInsert("contentList", content2, 1));
@ -111,8 +107,7 @@ public class AggregateChangeIdGenerationUnitTests { @@ -111,8 +107,7 @@ public class AggregateChangeIdGenerationUnitTests {
entity.contentMap.put("a", content);
entity.contentMap.put("b", content2);
AggregateChange<DummyEntity> aggregateChange = new AggregateChange<>(AggregateChange.Kind.SAVE, DummyEntity.class,
entity);
AggregateChange<DummyEntity> aggregateChange = AggregateChange.forSave(entity);
aggregateChange.addAction(rootInsert);
aggregateChange.addAction(createInsert("contentMap", content, "a"));
aggregateChange.addAction(createInsert("contentMap", content2, "b"));
@ -132,8 +127,7 @@ public class AggregateChangeIdGenerationUnitTests { @@ -132,8 +127,7 @@ public class AggregateChangeIdGenerationUnitTests {
DbAction.Insert<?> parentInsert = createInsert("single", content, null);
DbAction.Insert<?> insert = createDeepInsert("single", tag1, null, parentInsert);
AggregateChange<DummyEntity> aggregateChange = new AggregateChange<>(AggregateChange.Kind.SAVE, DummyEntity.class,
entity);
AggregateChange<DummyEntity> aggregateChange = AggregateChange.forSave(entity);
aggregateChange.addAction(rootInsert);
aggregateChange.addAction(parentInsert);
aggregateChange.addAction(insert);
@ -156,8 +150,7 @@ public class AggregateChangeIdGenerationUnitTests { @@ -156,8 +150,7 @@ public class AggregateChangeIdGenerationUnitTests {
DbAction.Insert<?> insert1 = createDeepInsert("tagList", tag1, 0, parentInsert);
DbAction.Insert<?> insert2 = createDeepInsert("tagList", tag2, 1, parentInsert);
AggregateChange<DummyEntity> aggregateChange = new AggregateChange<>(AggregateChange.Kind.SAVE, DummyEntity.class,
entity);
AggregateChange<DummyEntity> aggregateChange = AggregateChange.forSave(entity);
aggregateChange.addAction(rootInsert);
aggregateChange.addAction(parentInsert);
aggregateChange.addAction(insert1);
@ -184,8 +177,7 @@ public class AggregateChangeIdGenerationUnitTests { @@ -184,8 +177,7 @@ public class AggregateChangeIdGenerationUnitTests {
DbAction.Insert<?> insert1 = createDeepInsert("tagSet", tag1, null, parentInsert);
DbAction.Insert<?> insert2 = createDeepInsert("tagSet", tag2, null, parentInsert);
AggregateChange<DummyEntity> aggregateChange = new AggregateChange<>(AggregateChange.Kind.SAVE, DummyEntity.class,
entity);
AggregateChange<DummyEntity> aggregateChange = AggregateChange.forSave(entity);
aggregateChange.addAction(rootInsert);
aggregateChange.addAction(parentInsert);
aggregateChange.addAction(insert1);
@ -219,8 +211,7 @@ public class AggregateChangeIdGenerationUnitTests { @@ -219,8 +211,7 @@ public class AggregateChangeIdGenerationUnitTests {
DbAction.Insert<?> insert1 = createDeepInsert("single", tag1, null, parentInsert1);
DbAction.Insert<?> insert2 = createDeepInsert("single", tag2, null, parentInsert2);
AggregateChange<DummyEntity> aggregateChange = new AggregateChange<>(AggregateChange.Kind.SAVE, DummyEntity.class,
entity);
AggregateChange<DummyEntity> aggregateChange = AggregateChange.forSave(entity);
aggregateChange.addAction(rootInsert);
aggregateChange.addAction(parentInsert1);
aggregateChange.addAction(parentInsert2);
@ -253,8 +244,7 @@ public class AggregateChangeIdGenerationUnitTests { @@ -253,8 +244,7 @@ public class AggregateChangeIdGenerationUnitTests {
DbAction.Insert<?> insert2 = createDeepInsert("tagList", tag2, 0, parentInsert2);
DbAction.Insert<?> insert3 = createDeepInsert("tagList", tag3, 1, parentInsert2);
AggregateChange<DummyEntity> aggregateChange = new AggregateChange<>(AggregateChange.Kind.SAVE, DummyEntity.class,
entity);
AggregateChange<DummyEntity> aggregateChange = AggregateChange.forSave(entity);
aggregateChange.addAction(rootInsert);
aggregateChange.addAction(parentInsert1);
aggregateChange.addAction(parentInsert2);
@ -292,8 +282,7 @@ public class AggregateChangeIdGenerationUnitTests { @@ -292,8 +282,7 @@ public class AggregateChangeIdGenerationUnitTests {
DbAction.Insert<?> insert2 = createDeepInsert("tagMap", tag2, "222", parentInsert2);
DbAction.Insert<?> insert3 = createDeepInsert("tagMap", tag3, "333", parentInsert2);
AggregateChange<DummyEntity> aggregateChange = new AggregateChange<>(AggregateChange.Kind.SAVE, DummyEntity.class,
entity);
AggregateChange<DummyEntity> aggregateChange = AggregateChange.forSave(entity);
aggregateChange.addAction(rootInsert);
aggregateChange.addAction(parentInsert1);
aggregateChange.addAction(parentInsert2);
@ -348,11 +337,10 @@ public class AggregateChangeIdGenerationUnitTests { @@ -348,11 +337,10 @@ public class AggregateChangeIdGenerationUnitTests {
PersistentPropertyPath<RelationalPersistentProperty> toPath(DummyEntity root, Object pathValue) {
// DefaultPersistentPropertyPath is package-public
return new WritingContext(context, entity,
new AggregateChange<>(AggregateChange.Kind.SAVE, DummyEntity.class, root)).insert().stream()
.filter(a -> a instanceof DbAction.Insert).map(DbAction.Insert.class::cast)
.filter(a -> a.getEntity() == pathValue).map(DbAction.Insert::getPropertyPath).findFirst()
.orElseThrow(() -> new IllegalArgumentException("No matching path found"));
return new WritingContext(context, entity, AggregateChange.forSave(root)).insert().stream()
.filter(a -> a instanceof DbAction.Insert).map(DbAction.Insert.class::cast)
.filter(a -> a.getEntity() == pathValue).map(DbAction.Insert::getPropertyPath).findFirst()
.orElseThrow(() -> new IllegalArgumentException("No matching path found"));
}
private static class DummyEntity {

Loading…
Cancel
Save