Skip to content

Commit e5d7000

Browse files
schaudermp911de
authored andcommitted
Migrate ColumnInfos to use of the long path only.
Turns out the concept of base path becomes superfluous. Original pull request #1957 See #574
1 parent 208f209 commit e5d7000

File tree

9 files changed

+66
-39
lines changed

9 files changed

+66
-39
lines changed

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,15 +199,16 @@ private Identifier getParentKeys(DbAction.WithDependingOn<?> action, JdbcConvert
199199

200200
static Function<AggregatePath, Object> getIdMapper(Object idValue, AggregatePath path, JdbcConverter converter) {
201201

202+
RelationalPersistentProperty idProperty = path.getIdDefiningParentPath().getRequiredIdProperty();
202203
RelationalPersistentEntity<?> entity = converter.getMappingContext()
203-
.getPersistentEntity(path.getIdDefiningParentPath().getRequiredIdProperty());
204+
.getPersistentEntity(idProperty);
204205

205206
if (entity == null) {
206207
return aggregatePath -> idValue;
207208
}
208209

209210
PersistentPropertyPathAccessor<Object> propertyPathAccessor = entity.getPropertyPathAccessor(idValue);
210-
return aggregatePath -> propertyPathAccessor.getProperty(aggregatePath.getRequiredPersistentPropertyPath());
211+
return aggregatePath -> propertyPathAccessor.getProperty(aggregatePath.getSubPathBasedOn(idProperty.getActualType()).getRequiredPersistentPropertyPath());
211212
}
212213

213214
private Object getParentId(DbAction.WithDependingOn<?> action) {

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,17 @@ private static Function<AggregatePath, Object> getWrappedValueProvider(Function<
465465
RelationalPersistentProperty idProperty = idDefiningParentPath.getRequiredIdProperty();
466466
AggregatePath idPath = idProperty.isEntity() ? idDefiningParentPath.append(idProperty) : idDefiningParentPath;
467467

468-
return ap -> valueProvider.apply(idPath.append(ap));
468+
return ap -> valueProvider.apply(smartAppend(idPath, ap));
469+
}
470+
471+
private static AggregatePath smartAppend(AggregatePath base, AggregatePath suffix) {
472+
473+
RelationalPersistentEntity<?> owner = suffix.getRequiredBaseProperty().getOwner();
474+
if (owner.equals(base.getRequiredLeafEntity())) {
475+
return base.append(suffix);
476+
} else {
477+
return smartAppend(base, suffix.getTail());
478+
}
469479
}
470480

471481
/**

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -984,15 +984,16 @@ private Column getSingleNonNullColumn() {
984984
// return getTable(path).column(columnInfo.name()).as(columnInfo.alias());
985985

986986
AggregatePath.ColumnInfos columnInfos = mappingContext.getAggregatePath(entity).getTableInfo().idColumnInfos();
987-
return columnInfos.any((ap, ci) -> sqlContext.getTable(columnInfos.fullPath(ap)).column(ci.name()).as(ci.alias()));
987+
return columnInfos.any((ap, ci) -> sqlContext.getColumn(ap));
988988
}
989989

990990
private List<Column> getIdColumns() {
991991

992992
AggregatePath.ColumnInfos columnInfos = mappingContext.getAggregatePath(entity).getTableInfo().idColumnInfos();
993993

994+
// sqlcontext.getColumn (vs sqlContext.getTable
994995
return columnInfos
995-
.toColumnList((aggregatePath, columnInfo) -> sqlContext.getColumn(columnInfos.fullPath(aggregatePath)));
996+
.toColumnList((aggregatePath, columnInfo) -> sqlContext.getColumn(aggregatePath));
996997
}
997998

998999
private Column getVersionColumn() {

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,10 @@ <T> SqlIdentifierParameterSource forInsert(T instance, Class<T> domainType, Iden
8686
PersistentPropertyPathAccessor<T> propertyPathAccessor = persistentEntity.getPropertyPathAccessor(instance);
8787

8888
AggregatePath.ColumnInfos columnInfos = context.getAggregatePath(persistentEntity).getTableInfo().idColumnInfos();
89-
columnInfos.forEach((ap, __) -> {
90-
Object idValue = propertyPathAccessor.getProperty(columnInfos.fullPath(ap).getRequiredPersistentPropertyPath());
89+
90+
// fullPath: because we use the result with a PropertyPathAccessor
91+
columnInfos.forEachLong((ap, __) -> {
92+
Object idValue = propertyPathAccessor.getProperty(ap.getRequiredPersistentPropertyPath());
9193
RelationalPersistentProperty idProperty = ap.getRequiredLeafProperty();
9294
addConvertedPropertyValue(parameterSource, idProperty, idValue, idProperty.getColumnName());
9395
});

spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/JdbcIdentifierBuilderUnitTests.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,8 @@ static Function<AggregatePath, Object> getValueProvider(Object idValue, Aggregat
144144
if (entity == null) {
145145
return idValue;
146146
} else {
147+
148+
ap = ap.getTail();
147149
PersistentPropertyPathAccessor<Object> propertyPathAccessor = entity.getPropertyPathAccessor(idValue);
148150
return propertyPathAccessor.getProperty(ap.getRequiredPersistentPropertyPath());
149151
}

spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/AggregatePath.java

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.util.HashMap;
2222
import java.util.List;
2323
import java.util.Map;
24+
import java.util.TreeMap;
2425
import java.util.function.BiConsumer;
2526
import java.util.function.BiFunction;
2627
import java.util.function.BinaryOperator;
@@ -288,6 +289,8 @@ default int compareTo(AggregatePath other) {
288289
return toDotPath().compareTo(other.toDotPath());
289290
}
290291

292+
AggregatePath getSubPathBasedOn(Class<?> baseType);
293+
291294
/**
292295
* Information about a table underlying an entity.
293296
*
@@ -342,7 +345,7 @@ static TableInfo of(AggregatePath path) {
342345
private static ColumnInfos computeIdColumnInfos(AggregatePath tableOwner,
343346
RelationalPersistentEntity<?> leafEntity) {
344347

345-
ColumnInfos idColumnInfos = ColumnInfos.empty(tableOwner);
348+
ColumnInfos idColumnInfos = ColumnInfos.empty();
346349
if (!leafEntity.hasIdProperty()) {
347350
return idColumnInfos;
348351
}
@@ -369,7 +372,7 @@ private static ColumnInfos computeBackReferenceColumnInfos(AggregatePath path) {
369372
AggregatePath tableOwner = AggregatePathTraversal.getTableOwningPath(path);
370373

371374
if (tableOwner.isRoot()) {
372-
return ColumnInfos.empty(tableOwner);
375+
return ColumnInfos.empty();
373376
}
374377

375378
AggregatePath idDefiningParentPath = tableOwner.getIdDefiningParentPath();
@@ -438,7 +441,7 @@ public ColumnInfo reverseColumnInfo() {
438441
* @return ColumnInfos representing the effective id of this entity. Guaranteed not to be {@literal null}.
439442
*/
440443
public ColumnInfos effectiveIdColumnInfos() {
441-
return backReferenceColumnInfos.columnInfos.isEmpty() ? idColumnInfos : backReferenceColumnInfos;
444+
return backReferenceColumnInfos.isEmpty() ? idColumnInfos : backReferenceColumnInfos;
442445
}
443446
}
444447

@@ -483,33 +486,29 @@ static ColumnInfo of(AggregatePath path) {
483486
*/
484487
class ColumnInfos {
485488

486-
private final AggregatePath basePath;
487489
private final Map<AggregatePath, ColumnInfo> columnInfos;
488490
private final Map<Table, List<Column>> columnCache;
489491

490492
/**
491493
* Creates a new ColumnInfos instances based on the arguments.
492494
*
493-
* @param basePath The path on which all other paths in the other argument are based on. For the typical case of a
494-
* composite id, this would be the path to the composite ids.
495495
* @param columnInfos A map, mapping {@literal AggregatePath} instances to the respective {@literal ColumnInfo}
496496
*/
497-
ColumnInfos(AggregatePath basePath, Map<AggregatePath, ColumnInfo> columnInfos) {
497+
ColumnInfos(Map<AggregatePath, ColumnInfo> columnInfos) {
498498

499-
this.basePath = basePath;
500-
this.columnInfos = columnInfos;
499+
this.columnInfos = new TreeMap<>();
500+
this.columnInfos.putAll(columnInfos);
501501
this.columnCache = new HashMap<>(columnInfos.size(), 1f);
502502
}
503503

504504
/**
505505
* An empty {@literal ColumnInfos} instance with a fixed base path. Useful as a base when collecting
506506
* {@link ColumnInfo} instances into an {@literal ColumnInfos} instance.
507507
*
508-
* @param basePath The path on which paths in the {@literal ColumnInfos} or derived objects will be based on.
509508
* @return an empty instance save the {@literal basePath}.
510509
*/
511-
public static ColumnInfos empty(AggregatePath basePath) {
512-
return new ColumnInfos(basePath, new HashMap<>());
510+
public static ColumnInfos empty() {
511+
return new ColumnInfos(new HashMap<>());
513512
}
514513

515514
/**
@@ -549,8 +548,7 @@ public ColumnInfo any() {
549548
*/
550549
public List<Column> toColumnList(Table table) {
551550

552-
return columnCache.computeIfAbsent(table,
553-
t -> columnInfos.values().stream().map(columnInfo -> t.column(columnInfo.name)).toList());
551+
return columnCache.computeIfAbsent(table, t -> toColumnList((__, ci) -> t.column(ci.name)));
554552
}
555553

556554
/**
@@ -607,6 +605,15 @@ public void forEach(BiConsumer<AggregatePath, ColumnInfo> consumer) {
607605
columnInfos.forEach(consumer);
608606
}
609607

608+
/**
609+
* Calls the consumer for each pair of {@link AggregatePath} and {@literal ColumnInfo}.
610+
*
611+
* @param consumer the function to call.
612+
*/
613+
public void forEachLong(BiConsumer<AggregatePath, ColumnInfo> consumer) {
614+
columnInfos.forEach(consumer);
615+
}
616+
610617
/**
611618
* Calls the {@literal mapper} for each pair one pair of {@link AggregatePath} and {@link ColumnInfo}, if there is
612619
* any.
@@ -631,16 +638,6 @@ public ColumnInfo get(AggregatePath path) {
631638
return columnInfos.get(path);
632639
}
633640

634-
/**
635-
* Constructs an {@link AggregatePath} from the {@literal basePath} and the provided argument.
636-
*
637-
* @param ap {@literal AggregatePath} to be appended to the {@literal basePath}.
638-
* @return the combined (@literal AggregatePath}
639-
*/
640-
public AggregatePath fullPath(AggregatePath ap) {
641-
return basePath.append(ap);
642-
}
643-
644641
/**
645642
* Return an {@link Iterable} of {@link AggregatePath} associated with this column infos.
646643
*
@@ -668,5 +665,4 @@ public int size() {
668665
return columnInfos.size();
669666
}
670667
}
671-
672668
}

spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/ColumInfosBuilder.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ void add(RelationalPersistentProperty property, SqlIdentifier name, SqlIdentifie
6969
* @param columnInfo the {@literal ColumnInfo} added.
7070
*/
7171
void add(AggregatePath path, AggregatePath.ColumnInfo columnInfo) {
72-
columnInfoMap.put(path.subtract(basePath), columnInfo);
72+
columnInfoMap.put(path, columnInfo);
7373
}
7474

7575
/**
@@ -78,7 +78,7 @@ void add(AggregatePath path, AggregatePath.ColumnInfo columnInfo) {
7878
* @return a {@literal ColumnInfos} instance containing all the added {@link AggregatePath.ColumnInfo} instances.
7979
*/
8080
AggregatePath.ColumnInfos build() {
81-
return new AggregatePath.ColumnInfos(basePath, columnInfoMap);
81+
return new AggregatePath.ColumnInfos(columnInfoMap);
8282
}
8383

8484
}

spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/DefaultAggregatePath.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,24 @@ public AggregatePath subtract(@Nullable AggregatePath basePath) {
250250
throw new IllegalStateException("Can't subtract [%s] from [%s]".formatted(basePath, this));
251251
}
252252

253+
@Override
254+
public AggregatePath getSubPathBasedOn(Class<?> baseType) {
255+
256+
if (isRoot()) {
257+
if (rootType.getType() != baseType) {
258+
throw new IllegalStateException("No matching path found for [%s]".formatted(baseType));
259+
}
260+
return this;
261+
}
262+
263+
RelationalPersistentEntity<?> owner = getRequiredBaseProperty().getOwner();
264+
if (owner.getType() == baseType) {
265+
return this;
266+
}
267+
268+
return getTail().getSubPathBasedOn(baseType);
269+
}
270+
253271
/**
254272
* Creates an {@link Iterator} that iterates over the current path and all ancestors. It will start with the current
255273
* path, followed by its parent until ending with the root.

spring-data-relational/src/test/java/org/springframework/data/relational/core/mapping/ColumnInfosUnitTests.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class ColumnInfosUnitTests {
4141
@Test // GH-574
4242
void emptyColumnInfos() {
4343

44-
AggregatePath.ColumnInfos columnInfos = AggregatePath.ColumnInfos.empty(basePath(DummyEntity.class));
44+
AggregatePath.ColumnInfos columnInfos = AggregatePath.ColumnInfos.empty();
4545

4646
assertThat(columnInfos.isEmpty()).isTrue();
4747
assertThrows(NoSuchElementException.class, columnInfos::any);
@@ -76,10 +76,7 @@ void multiElementColumnInfos() {
7676

7777
List<String> collector = new ArrayList<>();
7878
columnInfos.forEach((ap, ci) -> collector.add(ap.toDotPath() + "+" + ci.name()));
79-
assertThat(collector).containsExactly("one+\"ONE\"", "two+\"TWO\"");
80-
81-
columnInfos.get(getPath(CompositeId.class, "one"));
82-
79+
assertThat(collector).containsExactly("id.one+\"ONE\"", "id.two+\"TWO\"");
8380
}
8481

8582
private AggregatePath getPath(Class<?> type, String name) {

0 commit comments

Comments
 (0)