Skip to content

Commit 3298a5e

Browse files
schaudermp911de
authored andcommitted
Applied changes requested in review.
The major ones are: * directly construct joins * remove multiple places of duplication * naming * documentation See #574 Original pull request #1957
1 parent 2bce737 commit 3298a5e

File tree

36 files changed

+926
-619
lines changed

36 files changed

+926
-619
lines changed

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

Lines changed: 23 additions & 7 deletions
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;
@@ -176,7 +177,8 @@ private Identifier getParentKeys(DbAction.WithDependingOn<?> action, JdbcConvert
176177
Object id = getParentId(action);
177178

178179
JdbcIdentifierBuilder identifier = JdbcIdentifierBuilder //
179-
.forBackReferences(converter, context.getAggregatePath(action.getPropertyPath()), id);
180+
.forBackReferences(converter, context.getAggregatePath(action.getPropertyPath()),
181+
getValueProvider(id, context.getAggregatePath(action.getPropertyPath()), converter));
180182

181183
for (Map.Entry<PersistentPropertyPath<RelationalPersistentProperty>, Object> qualifier : action.getQualifiers()
182184
.entrySet()) {
@@ -186,6 +188,22 @@ private Identifier getParentKeys(DbAction.WithDependingOn<?> action, JdbcConvert
186188
return identifier.build();
187189
}
188190

191+
static Function<AggregatePath, Object> getValueProvider(Object idValue, AggregatePath path, JdbcConverter converter) {
192+
193+
RelationalPersistentEntity<?> entity = converter.getMappingContext()
194+
.getPersistentEntity(path.getIdDefiningParentPath().getRequiredIdProperty().getType());
195+
196+
Function<AggregatePath, Object> valueProvider = ap -> {
197+
if (entity == null) {
198+
return idValue;
199+
} else {
200+
PersistentPropertyPathAccessor<Object> propertyPathAccessor = entity.getPropertyPathAccessor(idValue);
201+
return propertyPathAccessor.getProperty(ap.getRequiredPersistentPropertyPath());
202+
}
203+
};
204+
return valueProvider;
205+
}
206+
189207
private Object getParentId(DbAction.WithDependingOn<?> action) {
190208

191209
DbAction.WithEntity<?> idOwningAction = getIdOwningAction(action,
@@ -267,12 +285,10 @@ <T> List<T> populateIdsIfNecessary() {
267285

268286
if (newEntity != action.getEntity()) {
269287

270-
cascadingValues.stage(insert.getDependingOn(), insert.getPropertyPath(),
271-
qualifierValue, newEntity);
288+
cascadingValues.stage(insert.getDependingOn(), insert.getPropertyPath(), qualifierValue, newEntity);
272289
} else if (insert.getPropertyPath().getLeafProperty().isCollectionLike()) {
273290

274-
cascadingValues.gather(insert.getDependingOn(), insert.getPropertyPath(),
275-
qualifierValue, newEntity);
291+
cascadingValues.gather(insert.getDependingOn(), insert.getPropertyPath(), qualifierValue, newEntity);
276292
}
277293
}
278294
}
@@ -359,8 +375,8 @@ private <T> void updateWithVersion(DbAction.UpdateRoot<T> update) {
359375
*/
360376
private static class StagedValues {
361377

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

365381
Map<DbAction, Map<PersistentPropertyPath, StagedValue>> values = new HashMap<>();
366382

spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/Identifier.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ public static Identifier from(Map<SqlIdentifier, Object> map) {
106106
* @param identifier the identifier to append.
107107
* @return the {@link Identifier} containing all existing keys and the key part for {@code name}, {@code value}, and a
108108
* {@link Class target type}.
109-
* @since 3.5
109+
* @since 4.0
110110
*/
111111
public Identifier withPart(Identifier identifier) {
112112

@@ -207,7 +207,6 @@ public Object get(SqlIdentifier columnName) {
207207
return null;
208208
}
209209

210-
211210
/**
212211
* A single value of an Identifier consisting of the column name, the value and the target type which is to be used to
213212
* store the element in the database.

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

Lines changed: 31 additions & 24 deletions
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,31 +42,42 @@ 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+
public static JdbcIdentifierBuilder forBackReferences(JdbcConverter converter, AggregatePath path,
46+
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
53+
* {@literal null}.
54+
* @param path the path for which needs to back reference an id. Must not be {@literal null}.
55+
* @param defaultIdentifier Identifier to be used as a default when no backreference can be constructed. Must not be
56+
* {@literal null}.
57+
* @param valueProvider provides values for the {@link Identifier} based on an {@link AggregatePath}. Must not be
58+
* {@literal null}.
59+
* @return Guaranteed not to be {@literal null}.
60+
*/
61+
public static Identifier forBackReference(JdbcConverter converter, AggregatePath path, Identifier defaultIdentifier,
62+
Function<AggregatePath, Object> valueProvider) {
5663

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-
}
64+
Identifier identifierToUse = defaultIdentifier;
6465

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

67-
RelationalPersistentProperty property = ap.getRequiredLeafProperty();
68-
return Identifier.of(ci.name(), valueProvider.apply(ap),
69-
converter.getColumnType(property));
70-
}, Identifier::withPart);
68+
// note that the idDefiningParentPath might not itself have an id property, but have a combination of back
69+
// references and possibly keys, that form an id
70+
if (idDefiningParentPath.hasIdProperty()) {
71+
72+
AggregatePath.ColumnInfos infos = path.getTableInfo().backReferenceColumnInfos();
73+
identifierToUse = infos.reduce(Identifier.empty(), (ap, ci) -> {
74+
75+
RelationalPersistentProperty property = ap.getRequiredLeafProperty();
76+
return Identifier.of(ci.name(), valueProvider.apply(ap), converter.getColumnType(property));
77+
}, Identifier::withPart);
78+
}
7179

72-
return new JdbcIdentifierBuilder(identifierHolder);
80+
return identifierToUse;
7381
}
7482

7583
/**
@@ -85,8 +93,7 @@ public JdbcIdentifierBuilder withQualifier(AggregatePath path, Object value) {
8593
Assert.notNull(value, "Value must not be null");
8694

8795
AggregatePath.TableInfo tableInfo = path.getTableInfo();
88-
identifier = identifier.withPart(tableInfo.qualifierColumnInfo().name(), value,
89-
tableInfo.qualifierColumnType());
96+
identifier = identifier.withPart(tableInfo.qualifierColumnInfo().name(), value, tableInfo.qualifierColumnType());
9097

9198
return this;
9299
}

spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/MappingJdbcConverter.java

Lines changed: 20 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,8 @@ public <T> T getPropertyValue(RelationalPersistentProperty property) {
361361

362362
if (property.isCollectionLike() || property.isMap()) {
363363

364-
Identifier identifier = constructIdentifier(aggregatePath);
364+
Identifier identifier = JdbcIdentifierBuilder.forBackReference(MappingJdbcConverter.this, aggregatePath,
365+
this.identifier, getWrappedValueProvider(delegate::getValue, aggregatePath));
365366

366367
Iterable<Object> allByPath = relationResolver.findAllByPath(identifier,
367368
aggregatePath.getRequiredPersistentPropertyPath());
@@ -388,29 +389,6 @@ public <T> T getPropertyValue(RelationalPersistentProperty property) {
388389
return (T) delegate.getValue(aggregatePath);
389390
}
390391

391-
private Identifier constructIdentifier(AggregatePath aggregatePath) {
392-
393-
Identifier identifierToUse = this.identifier;
394-
AggregatePath idDefiningParentPath = aggregatePath.getIdDefiningParentPath();
395-
396-
// note that the idDefiningParentPath might not itself have an id property, but have a combination of back
397-
// references and possibly keys, that form an id
398-
if (idDefiningParentPath.hasIdProperty()) {
399-
400-
RelationalPersistentProperty idProperty = idDefiningParentPath.getRequiredIdProperty();
401-
AggregatePath idPath = idProperty.isEntity() ? idDefiningParentPath.append(idProperty) : idDefiningParentPath;
402-
Identifier[] buildingIdentifier = new Identifier[] { Identifier.empty() };
403-
aggregatePath.getTableInfo().reverseColumnInfos().forEach((ap, ci) -> {
404-
405-
Object value = delegate.getValue(idPath.append(ap));
406-
buildingIdentifier[0] = buildingIdentifier[0].withPart(ci.name(), value,
407-
ap.getRequiredLeafProperty().getActualType());
408-
});
409-
identifierToUse = buildingIdentifier[0];
410-
}
411-
return identifierToUse;
412-
}
413-
414392
@Override
415393
public boolean hasValue(RelationalPersistentProperty property) {
416394

@@ -431,7 +409,7 @@ public boolean hasValue(RelationalPersistentProperty property) {
431409
return delegate.hasValue(toUse);
432410
}
433411

434-
return delegate.hasValue(aggregatePath.getTableInfo().reverseColumnInfos().any().alias());
412+
return delegate.hasValue(aggregatePath.getTableInfo().backReferenceColumnInfos().any().alias());
435413
}
436414

437415
return delegate.hasValue(aggregatePath);
@@ -457,7 +435,7 @@ public boolean hasNonEmptyValue(RelationalPersistentProperty property) {
457435
return delegate.hasValue(toUse);
458436
}
459437

460-
return delegate.hasValue(aggregatePath.getTableInfo().reverseColumnInfos().any().alias());
438+
return delegate.hasValue(aggregatePath.getTableInfo().backReferenceColumnInfos().any().alias());
461439
}
462440

463441
return delegate.hasNonEmptyValue(aggregatePath);
@@ -472,6 +450,22 @@ public RelationalPropertyValueProvider withContext(ConversionContext context) {
472450
}
473451
}
474452

453+
private static Function<AggregatePath, Object> getWrappedValueProvider(Function<AggregatePath, Object> valueProvider,
454+
AggregatePath aggregatePath) {
455+
456+
AggregatePath idDefiningParentPath = aggregatePath.getIdDefiningParentPath();
457+
458+
if (!idDefiningParentPath.hasIdProperty()) {
459+
return ap -> {
460+
throw new IllegalStateException("This should never happen");
461+
};
462+
}
463+
464+
RelationalPersistentProperty idProperty = idDefiningParentPath.getRequiredIdProperty();
465+
AggregatePath idPath = idProperty.isEntity() ? idDefiningParentPath.append(idProperty) : idDefiningParentPath;
466+
return ap -> valueProvider.apply(idPath.append(ap));
467+
}
468+
475469
/**
476470
* Marker object to indicate that the property value provider should resolve relations.
477471
*

spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/SqlContext.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,11 @@ Column getColumn(AggregatePath path) {
6666
*
6767
* @param path must not be null.
6868
* @return a {@literal Column} that is part of the effective primary key for the given path.
69+
* @since 4.0
6970
*/
7071
Column getAnyReverseColumn(AggregatePath path) {
7172

72-
AggregatePath.ColumnInfo columnInfo = path.getTableInfo().reverseColumnInfos().any();
73+
AggregatePath.ColumnInfo columnInfo = path.getTableInfo().backReferenceColumnInfos().any();
7374
return getTable(path).column(columnInfo.name()).as(columnInfo.alias());
7475
}
7576
}

0 commit comments

Comments
 (0)