Skip to content

Commit 404730f

Browse files
committed
Merged two Identifier generating methods into one.
1 parent bb594d2 commit 404730f

File tree

6 files changed

+133
-114
lines changed

6 files changed

+133
-114
lines changed

Diff for: spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/JdbcAggregateChangeExecutionContext.java

+44-47
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import java.util.*;
1919
import java.util.function.BiConsumer;
20+
import java.util.function.Function;
2021
import java.util.stream.Collectors;
2122

2223
import org.springframework.dao.IncorrectUpdateSemanticsDataAccessException;
@@ -72,19 +73,16 @@ class JdbcAggregateChangeExecutionContext {
7273

7374
<T> void executeInsertRoot(DbAction.InsertRoot<T> insert) {
7475

75-
Object id = accessStrategy.insert(insert.getEntity(), insert.getEntityType(), Identifier.empty(),
76-
insert.getIdValueSource());
76+
Object id = accessStrategy.insert(insert.getEntity(), insert.getEntityType(), Identifier.empty(), insert.getIdValueSource());
7777
add(new DbActionExecutionResult(insert, id));
7878
}
7979

8080
<T> void executeBatchInsertRoot(DbAction.BatchInsertRoot<T> batchInsertRoot) {
8181

8282
List<DbAction.InsertRoot<T>> inserts = batchInsertRoot.getActions();
83-
List<InsertSubject<T>> insertSubjects = inserts.stream()
84-
.map(insert -> InsertSubject.describedBy(insert.getEntity(), Identifier.empty())).collect(Collectors.toList());
83+
List<InsertSubject<T>> insertSubjects = inserts.stream().map(insert -> InsertSubject.describedBy(insert.getEntity(), Identifier.empty())).collect(Collectors.toList());
8584

86-
Object[] ids = accessStrategy.insert(insertSubjects, batchInsertRoot.getEntityType(),
87-
batchInsertRoot.getBatchValue());
85+
Object[] ids = accessStrategy.insert(insertSubjects, batchInsertRoot.getEntityType(), batchInsertRoot.getBatchValue());
8886

8987
for (int i = 0; i < inserts.size(); i++) {
9088
add(new DbActionExecutionResult(inserts.get(i), ids.length > 0 ? ids[i] : null));
@@ -94,17 +92,14 @@ <T> void executeBatchInsertRoot(DbAction.BatchInsertRoot<T> batchInsertRoot) {
9492
<T> void executeInsert(DbAction.Insert<T> insert) {
9593

9694
Identifier parentKeys = getParentKeys(insert, converter);
97-
Object id = accessStrategy.insert(insert.getEntity(), insert.getEntityType(), parentKeys,
98-
insert.getIdValueSource());
95+
Object id = accessStrategy.insert(insert.getEntity(), insert.getEntityType(), parentKeys, insert.getIdValueSource());
9996
add(new DbActionExecutionResult(insert, id));
10097
}
10198

10299
<T> void executeBatchInsert(DbAction.BatchInsert<T> batchInsert) {
103100

104101
List<DbAction.Insert<T>> inserts = batchInsert.getActions();
105-
List<InsertSubject<T>> insertSubjects = inserts.stream()
106-
.map(insert -> InsertSubject.describedBy(insert.getEntity(), getParentKeys(insert, converter)))
107-
.collect(Collectors.toList());
102+
List<InsertSubject<T>> insertSubjects = inserts.stream().map(insert -> InsertSubject.describedBy(insert.getEntity(), getParentKeys(insert, converter))).collect(Collectors.toList());
108103

109104
Object[] ids = accessStrategy.insert(insertSubjects, batchInsert.getEntityType(), batchInsert.getBatchValue());
110105

@@ -176,20 +171,34 @@ private Identifier getParentKeys(DbAction.WithDependingOn<?> action, JdbcConvert
176171
Object id = getParentId(action);
177172

178173
JdbcIdentifierBuilder identifier = JdbcIdentifierBuilder //
179-
.forBackReferences(converter, context.getAggregatePath(action.getPropertyPath()), id);
174+
.forBackReferences(converter, context.getAggregatePath(action.getPropertyPath()),
175+
getValueProvider(id, context.getAggregatePath(action.getPropertyPath()), converter));
180176

181-
for (Map.Entry<PersistentPropertyPath<RelationalPersistentProperty>, Object> qualifier : action.getQualifiers()
182-
.entrySet()) {
177+
for (Map.Entry<PersistentPropertyPath<RelationalPersistentProperty>, Object> qualifier : action.getQualifiers().entrySet()) {
183178
identifier = identifier.withQualifier(context.getAggregatePath(qualifier.getKey()), qualifier.getValue());
184179
}
185180

186181
return identifier.build();
187182
}
188183

184+
static Function<AggregatePath, Object> getValueProvider(Object idValue, AggregatePath path, JdbcConverter converter) {
185+
186+
RelationalPersistentEntity<?> entity = converter.getMappingContext().getPersistentEntity(path.getIdDefiningParentPath().getRequiredIdProperty().getType());
187+
188+
Function<AggregatePath, Object> valueProvider = ap -> {
189+
if (entity == null) {
190+
return idValue;
191+
} else {
192+
PersistentPropertyPathAccessor<Object> propertyPathAccessor = entity.getPropertyPathAccessor(idValue);
193+
return propertyPathAccessor.getProperty(ap.getRequiredPersistentPropertyPath());
194+
}
195+
};
196+
return valueProvider;
197+
}
198+
189199
private Object getParentId(DbAction.WithDependingOn<?> action) {
190200

191-
DbAction.WithEntity<?> idOwningAction = getIdOwningAction(action,
192-
context.getAggregatePath(action.getPropertyPath()).getIdDefiningParentPath());
201+
DbAction.WithEntity<?> idOwningAction = getIdOwningAction(action, context.getAggregatePath(action.getPropertyPath()).getIdDefiningParentPath());
193202

194203
return getPotentialGeneratedIdFrom(idOwningAction);
195204
}
@@ -198,8 +207,7 @@ private DbAction.WithEntity<?> getIdOwningAction(DbAction.WithEntity<?> action,
198207

199208
if (!(action instanceof DbAction.WithDependingOn<?> withDependingOn)) {
200209

201-
Assert.state(idPath.isRoot(),
202-
"When the id path is not empty the id providing action should be of type WithDependingOn");
210+
Assert.state(idPath.isRoot(), "When the id path is not empty the id providing action should be of type WithDependingOn");
203211

204212
return action;
205213
}
@@ -267,20 +275,16 @@ <T> List<T> populateIdsIfNecessary() {
267275

268276
if (newEntity != action.getEntity()) {
269277

270-
cascadingValues.stage(insert.getDependingOn(), insert.getPropertyPath(),
271-
qualifierValue, newEntity);
278+
cascadingValues.stage(insert.getDependingOn(), insert.getPropertyPath(), qualifierValue, newEntity);
272279
} else if (insert.getPropertyPath().getLeafProperty().isCollectionLike()) {
273280

274-
cascadingValues.gather(insert.getDependingOn(), insert.getPropertyPath(),
275-
qualifierValue, newEntity);
281+
cascadingValues.gather(insert.getDependingOn(), insert.getPropertyPath(), qualifierValue, newEntity);
276282
}
277283
}
278284
}
279285

280286
if (roots.isEmpty()) {
281-
throw new IllegalStateException(
282-
String.format("Cannot retrieve the resulting instance(s) unless a %s or %s action was successfully executed",
283-
DbAction.InsertRoot.class.getName(), DbAction.UpdateRoot.class.getName()));
287+
throw new IllegalStateException(String.format("Cannot retrieve the resulting instance(s) unless a %s or %s action was successfully executed", DbAction.InsertRoot.class.getName(), DbAction.UpdateRoot.class.getName()));
284288
}
285289

286290
Collections.reverse(roots);
@@ -289,23 +293,19 @@ <T> List<T> populateIdsIfNecessary() {
289293
}
290294

291295
@SuppressWarnings("unchecked")
292-
private <S> Object setIdAndCascadingProperties(DbAction.WithEntity<S> action, @Nullable Object generatedId,
293-
StagedValues cascadingValues) {
296+
private <S> Object setIdAndCascadingProperties(DbAction.WithEntity<S> action, @Nullable Object generatedId, StagedValues cascadingValues) {
294297

295298
S originalEntity = action.getEntity();
296299

297-
RelationalPersistentEntity<S> persistentEntity = (RelationalPersistentEntity<S>) context
298-
.getRequiredPersistentEntity(action.getEntityType());
299-
PersistentPropertyPathAccessor<S> propertyAccessor = converter.getPropertyAccessor(persistentEntity,
300-
originalEntity);
300+
RelationalPersistentEntity<S> persistentEntity = (RelationalPersistentEntity<S>) context.getRequiredPersistentEntity(action.getEntityType());
301+
PersistentPropertyPathAccessor<S> propertyAccessor = converter.getPropertyAccessor(persistentEntity, originalEntity);
301302

302303
if (IdValueSource.GENERATED.equals(action.getIdValueSource())) {
303304
propertyAccessor.setProperty(persistentEntity.getRequiredIdProperty(), generatedId);
304305
}
305306

306307
// set values of changed immutables referenced by this entity
307-
cascadingValues.forEachPath(action, (persistentPropertyPath, o) -> propertyAccessor
308-
.setProperty(getRelativePath(action, persistentPropertyPath), o));
308+
cascadingValues.forEachPath(action, (persistentPropertyPath, o) -> propertyAccessor.setProperty(getRelativePath(action, persistentPropertyPath), o));
309309

310310
return propertyAccessor.getBean();
311311
}
@@ -337,8 +337,7 @@ private <T> void updateWithoutVersion(DbAction.UpdateRoot<T> update) {
337337

338338
if (!accessStrategy.update(update.getEntity(), update.getEntityType())) {
339339

340-
throw new IncorrectUpdateSemanticsDataAccessException(
341-
String.format(UPDATE_FAILED, update.getEntity(), getIdFrom(update)));
340+
throw new IncorrectUpdateSemanticsDataAccessException(String.format(UPDATE_FAILED, update.getEntity(), getIdFrom(update)));
342341
}
343342
}
344343

@@ -359,21 +358,20 @@ private <T> void updateWithVersion(DbAction.UpdateRoot<T> update) {
359358
*/
360359
private static class StagedValues {
361360

362-
static final List<MultiValueAggregator<?>> aggregators = Arrays.asList(SetAggregator.INSTANCE, MapAggregator.INSTANCE,
363-
ListAggregator.INSTANCE, SingleElementAggregator.INSTANCE);
361+
static final List<MultiValueAggregator<?>> aggregators = Arrays.asList(SetAggregator.INSTANCE, MapAggregator.INSTANCE, ListAggregator.INSTANCE, SingleElementAggregator.INSTANCE);
364362

365363
Map<DbAction, Map<PersistentPropertyPath, StagedValue>> values = new HashMap<>();
366364

367365
/**
368366
* Adds a value that needs to be set in an entity higher up in the tree of entities in the aggregate. If the
369367
* attribute to be set is multivalued this method expects only a single element.
370368
*
371-
* @param action The action responsible for persisting the entity that needs the added value set. Must not be
372-
* {@literal null}.
373-
* @param path The path to the property in which to set the value. Must not be {@literal null}.
369+
* @param action The action responsible for persisting the entity that needs the added value set. Must not be
370+
* {@literal null}.
371+
* @param path The path to the property in which to set the value. Must not be {@literal null}.
374372
* @param qualifier If {@code path} is a qualified multivalued properties this parameter contains the qualifier. May
375-
* be {@literal null}.
376-
* @param value The value to be set. Must not be {@literal null}.
373+
* be {@literal null}.
374+
* @param value The value to be set. Must not be {@literal null}.
377375
*/
378376
void stage(DbAction<?> action, PersistentPropertyPath path, @Nullable Object qualifier, Object value) {
379377

@@ -386,11 +384,9 @@ <T> StagedValue gather(DbAction<?> action, PersistentPropertyPath path, @Nullabl
386384

387385
MultiValueAggregator<T> aggregator = getAggregatorFor(path);
388386

389-
Map<PersistentPropertyPath, StagedValue> valuesForPath = this.values.computeIfAbsent(action,
390-
dbAction -> new HashMap<>());
387+
Map<PersistentPropertyPath, StagedValue> valuesForPath = this.values.computeIfAbsent(action, dbAction -> new HashMap<>());
391388

392-
StagedValue stagedValue = valuesForPath.computeIfAbsent(path,
393-
persistentPropertyPath -> new StagedValue(aggregator.createEmptyInstance()));
389+
StagedValue stagedValue = valuesForPath.computeIfAbsent(path, persistentPropertyPath -> new StagedValue(aggregator.createEmptyInstance()));
394390
T currentValue = (T) stagedValue.value;
395391

396392
stagedValue.value = aggregator.add(currentValue, qualifier, value);
@@ -430,7 +426,8 @@ void forEachPath(DbAction<?> dbAction, BiConsumer<PersistentPropertyPath, Object
430426
}
431427

432428
private static class StagedValue {
433-
@Nullable Object value;
429+
@Nullable
430+
Object value;
434431
boolean isStaged;
435432

436433
public StagedValue(@Nullable Object value) {

Diff for: spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/JdbcIdentifierBuilder.java

+29-23
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,7 @@
1717

1818
import java.util.function.Function;
1919

20-
import org.springframework.data.mapping.PersistentPropertyPathAccessor;
2120
import org.springframework.data.relational.core.mapping.AggregatePath;
22-
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
23-
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
2421
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
2522
import org.springframework.util.Assert;
2623

@@ -45,37 +42,46 @@ public static JdbcIdentifierBuilder empty() {
4542
/**
4643
* Creates ParentKeys with backreference for the given path and value of the parents id.
4744
*/
48-
public static JdbcIdentifierBuilder forBackReferences(JdbcConverter converter, AggregatePath path, Object value) {
45+
// gets called during insert. value contains the id from an insert of the parent
46+
public static JdbcIdentifierBuilder forBackReferences(JdbcConverter converter, AggregatePath path, Function<AggregatePath, Object> valueProvider) {
4947

50-
RelationalPersistentProperty idProperty = path.getIdDefiningParentPath().getRequiredIdProperty();
51-
AggregatePath.ColumnInfos infos = path.getTableInfo().reverseColumnInfos();
48+
return new JdbcIdentifierBuilder(forBackReference(converter, path, Identifier.empty(), valueProvider));
49+
}
5250

53-
// create property accessor
54-
RelationalMappingContext mappingContext = converter.getMappingContext();
55-
RelationalPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(idProperty.getType());
51+
/**
52+
* @param converter used for determining the column types to be used for different properties. Must not be {@literal null}.
53+
* @param path the path for which needs to back reference an id. Must not be {@literal null}.
54+
* @param defaultIdentifier Identifier to be used as a default when no backreference can be constructed. Must not be {@literal null}.
55+
* @param valueProvider provides values for the {@link Identifier} based on an {@link AggregatePath}. Must not be {@literal null}.
56+
* @return Guaranteed not to be {@literal null}.
57+
*/
58+
public static Identifier forBackReference(JdbcConverter converter, AggregatePath path, Identifier defaultIdentifier, Function<AggregatePath, Object> valueProvider) {
5659

57-
Function<AggregatePath, Object> valueProvider;
58-
if (persistentEntity == null) {
59-
valueProvider = ap -> value;
60-
} else {
61-
PersistentPropertyPathAccessor<Object> propertyPathAccessor = persistentEntity.getPropertyPathAccessor(value);
62-
valueProvider = ap -> propertyPathAccessor.getProperty(ap.getRequiredPersistentPropertyPath());
63-
}
60+
Identifier identifierToUse = defaultIdentifier;
6461

65-
Identifier identifierHolder = infos.reduce(Identifier.empty(), (ap, ci) -> {
62+
AggregatePath idDefiningParentPath = path.getIdDefiningParentPath();
6663

67-
RelationalPersistentProperty property = ap.getRequiredLeafProperty();
68-
return Identifier.of(ci.name(), valueProvider.apply(ap),
69-
converter.getColumnType(property));
70-
}, Identifier::withPart);
64+
// note that the idDefiningParentPath might not itself have an id property, but have a combination of back
65+
// references and possibly keys, that form an id
66+
if (idDefiningParentPath.hasIdProperty()) {
7167

72-
return new JdbcIdentifierBuilder(identifierHolder);
68+
AggregatePath.ColumnInfos infos = path.getTableInfo().reverseColumnInfos();
69+
identifierToUse = infos.reduce(Identifier.empty(), (ap, ci) -> {
70+
71+
RelationalPersistentProperty property = ap.getRequiredLeafProperty();
72+
return Identifier.of(ci.name(), valueProvider.apply(ap),
73+
converter.getColumnType(property));
74+
}, Identifier::withPart);
75+
}
76+
77+
return identifierToUse;
7378
}
7479

80+
7581
/**
7682
* Adds a qualifier to the identifier to build. A qualifier is a map key or a list index.
7783
*
78-
* @param path path to the map that gets qualified by {@code value}. Must not be {@literal null}.
84+
* @param path path to the map that gets qualified by {@code value}. Must not be {@literal null}.
7985
* @param value map key or list index qualifying the map identified by {@code path}. Must not be {@literal null}.
8086
* @return this builder. Guaranteed to be not {@literal null}.
8187
*/

0 commit comments

Comments
 (0)