Skip to content

Commit d00e928

Browse files
committed
Introduce AggregatePath.
AggregatePath replaces PersistentPropertyPathExtension. It gets created and cached by the RelationalMappingContext, which should be more efficient and certainly looks nicer. Closes #1525 Original pull request #1486
1 parent 7d5bc1c commit d00e928

File tree

44 files changed

+1784
-289
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+1784
-289
lines changed

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

+10-23
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,7 @@
1515
*/
1616
package org.springframework.data.jdbc.core;
1717

18-
import java.util.ArrayList;
19-
import java.util.Arrays;
20-
import java.util.Collections;
21-
import java.util.HashMap;
22-
import java.util.HashSet;
23-
import java.util.LinkedHashMap;
24-
import java.util.List;
25-
import java.util.Map;
26-
import java.util.Optional;
27-
import java.util.Set;
18+
import java.util.*;
2819
import java.util.function.BiConsumer;
2920
import java.util.stream.Collectors;
3021

@@ -38,11 +29,12 @@
3829
import org.springframework.data.mapping.PersistentProperty;
3930
import org.springframework.data.mapping.PersistentPropertyPath;
4031
import org.springframework.data.mapping.PersistentPropertyPathAccessor;
41-
import org.springframework.data.mapping.context.MappingContext;
4232
import org.springframework.data.relational.core.conversion.DbAction;
4333
import org.springframework.data.relational.core.conversion.DbActionExecutionResult;
4434
import org.springframework.data.relational.core.conversion.IdValueSource;
35+
import org.springframework.data.relational.core.mapping.AggregatePath;
4536
import org.springframework.data.relational.core.mapping.PersistentPropertyPathExtension;
37+
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
4638
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
4739
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
4840
import org.springframework.data.relational.core.sql.LockMode;
@@ -65,7 +57,7 @@ class JdbcAggregateChangeExecutionContext {
6557
private static final String UPDATE_FAILED = "Failed to update entity [%s]; Id [%s] not found in database";
6658
private static final String UPDATE_FAILED_OPTIMISTIC_LOCKING = "Failed to update entity [%s]; The entity was updated since it was rea or it isn't in the database at all";
6759

68-
private final MappingContext<? extends RelationalPersistentEntity<?>, ? extends RelationalPersistentProperty> context;
60+
private final RelationalMappingContext context;
6961
private final JdbcConverter converter;
7062
private final DataAccessStrategy accessStrategy;
7163

@@ -184,39 +176,34 @@ private Identifier getParentKeys(DbAction.WithDependingOn<?> action, JdbcConvert
184176
Object id = getParentId(action);
185177

186178
JdbcIdentifierBuilder identifier = JdbcIdentifierBuilder //
187-
.forBackReferences(converter, new PersistentPropertyPathExtension(context, action.getPropertyPath()), id);
179+
.forBackReferences(converter, context.getAggregatePath(action.getPropertyPath()), id);
188180

189181
for (Map.Entry<PersistentPropertyPath<RelationalPersistentProperty>, Object> qualifier : action.getQualifiers()
190182
.entrySet()) {
191-
identifier = identifier.withQualifier(new PersistentPropertyPathExtension(context, qualifier.getKey()),
192-
qualifier.getValue());
183+
identifier = identifier.withQualifier(context.getAggregatePath(qualifier.getKey()), qualifier.getValue());
193184
}
194185

195186
return identifier.build();
196187
}
197188

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

200-
PersistentPropertyPathExtension path = new PersistentPropertyPathExtension(context, action.getPropertyPath());
201-
PersistentPropertyPathExtension idPath = path.getIdDefiningParentPath();
202-
203-
DbAction.WithEntity<?> idOwningAction = getIdOwningAction(action, idPath);
191+
DbAction.WithEntity<?> idOwningAction = getIdOwningAction(action, context.getAggregatePath(action.getPropertyPath()).getIdDefiningParentPath());
204192

205193
return getPotentialGeneratedIdFrom(idOwningAction);
206194
}
207195

208-
private DbAction.WithEntity<?> getIdOwningAction(DbAction.WithEntity<?> action,
209-
PersistentPropertyPathExtension idPath) {
196+
private DbAction.WithEntity<?> getIdOwningAction(DbAction.WithEntity<?> action, AggregatePath idPath) {
210197

211198
if (!(action instanceof DbAction.WithDependingOn<?> withDependingOn)) {
212199

213-
Assert.state(idPath.getLength() == 0,
200+
Assert.state(idPath.isRoot(),
214201
"When the id path is not empty the id providing action should be of type WithDependingOn");
215202

216203
return action;
217204
}
218205

219-
if (idPath.matches(withDependingOn.getPropertyPath())) {
206+
if (idPath.equals(context.getAggregatePath(withDependingOn.getPropertyPath()))) {
220207
return action;
221208
}
222209

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

+19-16
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@
4747
import org.springframework.data.mapping.model.SpELExpressionParameterValueProvider;
4848
import org.springframework.data.relational.core.conversion.BasicRelationalConverter;
4949
import org.springframework.data.relational.core.conversion.RelationalConverter;
50-
import org.springframework.data.relational.core.mapping.PersistentPropertyPathExtension;
50+
import org.springframework.data.relational.core.mapping.AggregatePath;
51+
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
5152
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
5253
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
5354
import org.springframework.data.relational.core.sql.IdentifierProcessing;
@@ -86,14 +87,14 @@ public class BasicJdbcConverter extends BasicRelationalConverter implements Jdbc
8687
* Creates a new {@link BasicRelationalConverter} given {@link MappingContext} and a
8788
* {@link JdbcTypeFactory#unsupported() no-op type factory} throwing {@link UnsupportedOperationException} on type
8889
* creation. Use
89-
* {@link #BasicJdbcConverter(MappingContext, RelationResolver, CustomConversions, JdbcTypeFactory, IdentifierProcessing)}
90+
* {@link #BasicJdbcConverter(RelationalMappingContext, RelationResolver, CustomConversions, JdbcTypeFactory, IdentifierProcessing)}
9091
* (MappingContext, RelationResolver, JdbcTypeFactory)} to convert arrays and large objects into JDBC-specific types.
9192
*
9293
* @param context must not be {@literal null}.
9394
* @param relationResolver used to fetch additional relations from the database. Must not be {@literal null}.
9495
*/
9596
public BasicJdbcConverter(
96-
MappingContext<? extends RelationalPersistentEntity<?>, ? extends RelationalPersistentProperty> context,
97+
RelationalMappingContext context,
9798
RelationResolver relationResolver) {
9899

99100
super(context, new JdbcCustomConversions());
@@ -116,7 +117,7 @@ public BasicJdbcConverter(
116117
* @since 2.0
117118
*/
118119
public BasicJdbcConverter(
119-
MappingContext<? extends RelationalPersistentEntity<?>, ? extends RelationalPersistentProperty> context,
120+
RelationalMappingContext context,
120121
RelationResolver relationResolver, CustomConversions conversions, JdbcTypeFactory typeFactory,
121122
IdentifierProcessing identifierProcessing) {
122123

@@ -300,12 +301,13 @@ private JdbcValue tryToConvertToJdbcValue(@Nullable Object value) {
300301

301302
@Override
302303
public <T> T mapRow(RelationalPersistentEntity<T> entity, ResultSet resultSet, Object key) {
303-
return new ReadingContext<T>(new PersistentPropertyPathExtension(getMappingContext(), entity),
304+
return new ReadingContext<T>(getMappingContext().getAggregatePath( entity),
304305
new ResultSetAccessor(resultSet), Identifier.empty(), key).mapRow();
305306
}
306307

308+
307309
@Override
308-
public <T> T mapRow(PersistentPropertyPathExtension path, ResultSet resultSet, Identifier identifier, Object key) {
310+
public <T> T mapRow(AggregatePath path, ResultSet resultSet, Identifier identifier, Object key) {
309311
return new ReadingContext<T>(path, new ResultSetAccessor(resultSet), identifier, key).mapRow();
310312
}
311313

@@ -350,8 +352,8 @@ private class ReadingContext<T> {
350352

351353
private final RelationalPersistentEntity<T> entity;
352354

353-
private final PersistentPropertyPathExtension rootPath;
354-
private final PersistentPropertyPathExtension path;
355+
private final AggregatePath rootPath;
356+
private final AggregatePath path;
355357
private final Identifier identifier;
356358
private final Object key;
357359

@@ -360,26 +362,27 @@ private class ReadingContext<T> {
360362
private final ResultSetAccessor accessor;
361363

362364
@SuppressWarnings("unchecked")
363-
private ReadingContext(PersistentPropertyPathExtension rootPath, ResultSetAccessor accessor, Identifier identifier,
365+
private ReadingContext(AggregatePath rootPath, ResultSetAccessor accessor, Identifier identifier,
364366
Object key) {
365367
RelationalPersistentEntity<T> entity = (RelationalPersistentEntity<T>) rootPath.getLeafEntity();
366368

367369
Assert.notNull(entity, "The rootPath must point to an entity");
368370

369371
this.entity = entity;
370372
this.rootPath = rootPath;
371-
this.path = new PersistentPropertyPathExtension(getMappingContext(), this.entity);
373+
this.path = getMappingContext().getAggregatePath( this.entity);
372374
this.identifier = identifier;
373375
this.key = key;
374376
this.propertyValueProvider = new JdbcPropertyValueProvider(path, accessor);
375377
this.backReferencePropertyValueProvider = new JdbcBackReferencePropertyValueProvider(path, accessor);
376378
this.accessor = accessor;
377379
}
378380

379-
private ReadingContext(RelationalPersistentEntity<T> entity, PersistentPropertyPathExtension rootPath,
380-
PersistentPropertyPathExtension path, Identifier identifier, Object key,
381+
private ReadingContext(RelationalPersistentEntity<T> entity, AggregatePath rootPath,
382+
AggregatePath path, Identifier identifier, Object key,
381383
JdbcPropertyValueProvider propertyValueProvider,
382384
JdbcBackReferencePropertyValueProvider backReferencePropertyValueProvider, ResultSetAccessor accessor) {
385+
383386
this.entity = entity;
384387
this.rootPath = rootPath;
385388
this.path = path;
@@ -393,7 +396,7 @@ private ReadingContext(RelationalPersistentEntity<T> entity, PersistentPropertyP
393396
private <S> ReadingContext<S> extendBy(RelationalPersistentProperty property) {
394397
return new ReadingContext<>(
395398
(RelationalPersistentEntity<S>) getMappingContext().getRequiredPersistentEntity(property.getActualType()),
396-
rootPath.extendBy(property), path.extendBy(property), identifier, key,
399+
rootPath.append(property), path.append(property), identifier, key,
397400
propertyValueProvider.extendBy(property), backReferencePropertyValueProvider.extendBy(property), accessor);
398401
}
399402

@@ -453,10 +456,10 @@ private Object readOrLoadProperty(@Nullable Object id, RelationalPersistentPrope
453456
private Iterable<Object> resolveRelation(@Nullable Object id, RelationalPersistentProperty property) {
454457

455458
Identifier identifier = id == null //
456-
? this.identifier.withPart(rootPath.getQualifierColumn(), key, Object.class) //
457-
: Identifier.of(rootPath.extendBy(property).getReverseColumnName(), id, Object.class);
459+
? this.identifier.withPart(rootPath.getTableInfo().qualifierColumnInfo().name(), key, Object.class) //
460+
: Identifier.of(rootPath.append(property).getTableInfo().reverseColumnInfo().name(), id, Object.class);
458461

459-
PersistentPropertyPath<? extends RelationalPersistentProperty> propertyPath = path.extendBy(property)
462+
PersistentPropertyPath<? extends RelationalPersistentProperty> propertyPath = path.append(property)
460463
.getRequiredPersistentPropertyPath();
461464

462465
return relationResolver.findAllByPath(identifier, propertyPath);

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

+9-9
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,12 @@
2828
import org.springframework.data.domain.Sort;
2929
import org.springframework.data.mapping.PersistentPropertyPath;
3030
import org.springframework.data.relational.core.conversion.IdValueSource;
31+
import org.springframework.data.relational.core.mapping.AggregatePath;
3132
import org.springframework.data.relational.core.mapping.PersistentPropertyPathExtension;
3233
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
3334
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
3435
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
3536
import org.springframework.data.relational.core.query.Query;
36-
import org.springframework.data.relational.core.sql.IdentifierProcessing;
3737
import org.springframework.data.relational.core.sql.LockMode;
3838
import org.springframework.data.relational.core.sql.SqlIdentifier;
3939
import org.springframework.jdbc.core.RowMapper;
@@ -297,8 +297,8 @@ public Iterable<Object> findAllByPath(Identifier identifier,
297297
Assert.notNull(identifier, "identifier must not be null");
298298
Assert.notNull(propertyPath, "propertyPath must not be null");
299299

300-
PersistentPropertyPathExtension path = new PersistentPropertyPathExtension(context, propertyPath);
301-
Class<?> actualType = path.getActualType();
300+
AggregatePath path = context.getAggregatePath(propertyPath);
301+
Class<?> actualType = path.getLeafEntity().getType();
302302

303303
String findAllByProperty = sql(actualType) //
304304
.getFindAllByProperty(identifier, propertyPath);
@@ -339,8 +339,7 @@ public <T> Optional<T> findOne(Query query, Class<T> domainType) {
339339
String sqlQuery = sql(domainType).selectByQuery(query, parameterSource);
340340

341341
try {
342-
return Optional.ofNullable(
343-
operations.queryForObject(sqlQuery, parameterSource, getEntityRowMapper(domainType)));
342+
return Optional.ofNullable(operations.queryForObject(sqlQuery, parameterSource, getEntityRowMapper(domainType)));
344343
} catch (EmptyResultDataAccessException e) {
345344
return Optional.empty();
346345
}
@@ -394,14 +393,15 @@ private <T> EntityRowMapper<T> getEntityRowMapper(Class<T> domainType) {
394393
return new EntityRowMapper<>(getRequiredPersistentEntity(domainType), converter);
395394
}
396395

397-
private EntityRowMapper<?> getEntityRowMapper(PersistentPropertyPathExtension path, Identifier identifier) {
396+
private EntityRowMapper<?> getEntityRowMapper(AggregatePath path, Identifier identifier) {
398397
return new EntityRowMapper<>(path, converter, identifier);
399398
}
400399

401-
private RowMapper<?> getMapEntityRowMapper(PersistentPropertyPathExtension path, Identifier identifier) {
400+
private RowMapper<?> getMapEntityRowMapper(AggregatePath path, Identifier identifier) {
402401

403-
SqlIdentifier keyColumn = path.getQualifierColumn();
404-
Assert.notNull(keyColumn, () -> "KeyColumn must not be null for " + path);
402+
AggregatePath.ColumnInfo qualifierColumnInfo = path.getTableInfo().qualifierColumnInfo();
403+
Assert.notNull(qualifierColumnInfo, () -> "Qualifier column must not be null for " + path);
404+
SqlIdentifier keyColumn = qualifierColumnInfo.name();
405405

406406
return new MapEntityRowMapper<>(path, converter, identifier, keyColumn);
407407
}

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

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

1818
import java.sql.ResultSet;
1919

20+
import org.springframework.data.relational.core.mapping.AggregatePath;
2021
import org.springframework.data.relational.core.mapping.PersistentPropertyPathExtension;
2122
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
2223
import org.springframework.jdbc.core.RowMapper;
@@ -35,13 +36,28 @@
3536
public class EntityRowMapper<T> implements RowMapper<T> {
3637

3738
private final RelationalPersistentEntity<T> entity;
38-
private final PersistentPropertyPathExtension path;
39+
private final AggregatePath path;
3940
private final JdbcConverter converter;
4041
private final Identifier identifier;
4142

43+
/**
44+
*
45+
*
46+
* @deprecated use {@link EntityRowMapper#EntityRowMapper(AggregatePath, JdbcConverter, Identifier)} instead
47+
*/
48+
@Deprecated(since = "3.2", forRemoval = true)
4249
@SuppressWarnings("unchecked")
4350
public EntityRowMapper(PersistentPropertyPathExtension path, JdbcConverter converter, Identifier identifier) {
4451

52+
this.entity = (RelationalPersistentEntity<T>) path.getLeafEntity();
53+
this.path = path.getAggregatePath();
54+
this.converter = converter;
55+
this.identifier = identifier;
56+
}
57+
58+
@SuppressWarnings("unchecked")
59+
public EntityRowMapper(AggregatePath path, JdbcConverter converter, Identifier identifier) {
60+
4561
this.entity = (RelationalPersistentEntity<T>) path.getLeafEntity();
4662
this.path = path;
4763
this.converter = converter;

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

+5-6
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,8 @@
1616
package org.springframework.data.jdbc.core.convert;
1717

1818
import org.springframework.data.mapping.model.PropertyValueProvider;
19-
import org.springframework.data.relational.core.mapping.PersistentPropertyPathExtension;
19+
import org.springframework.data.relational.core.mapping.AggregatePath;
2020
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
21-
import org.springframework.data.relational.core.sql.IdentifierProcessing;
2221

2322
/**
2423
* {@link PropertyValueProvider} obtaining values from a {@link ResultSetAccessor}. For a given id property it provides
@@ -31,25 +30,25 @@
3130
*/
3231
class JdbcBackReferencePropertyValueProvider implements PropertyValueProvider<RelationalPersistentProperty> {
3332

34-
private final PersistentPropertyPathExtension basePath;
33+
private final AggregatePath basePath;
3534
private final ResultSetAccessor resultSet;
3635

3736
/**
3837
* @param basePath path from the aggregate root relative to which all properties get resolved.
3938
* @param resultSet the {@link ResultSetAccessor} from which to obtain the actual values.
4039
*/
41-
JdbcBackReferencePropertyValueProvider(PersistentPropertyPathExtension basePath, ResultSetAccessor resultSet) {
40+
JdbcBackReferencePropertyValueProvider(AggregatePath basePath, ResultSetAccessor resultSet) {
4241

4342
this.resultSet = resultSet;
4443
this.basePath = basePath;
4544
}
4645

4746
@Override
4847
public <T> T getPropertyValue(RelationalPersistentProperty property) {
49-
return (T) resultSet.getObject(basePath.extendBy(property).getReverseColumnNameAlias().getReference());
48+
return (T) resultSet.getObject(basePath.append(property).getTableInfo().reverseColumnInfo().alias().getReference());
5049
}
5150

5251
public JdbcBackReferencePropertyValueProvider extendBy(RelationalPersistentProperty property) {
53-
return new JdbcBackReferencePropertyValueProvider(basePath.extendBy(property), resultSet);
52+
return new JdbcBackReferencePropertyValueProvider(basePath.append(property), resultSet);
5453
}
5554
}

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

+23-1
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,11 @@
1919
import java.sql.SQLType;
2020

2121
import org.springframework.data.jdbc.core.mapping.JdbcValue;
22+
import org.springframework.data.mapping.context.MappingContext;
2223
import org.springframework.data.relational.core.conversion.RelationalConverter;
24+
import org.springframework.data.relational.core.mapping.AggregatePath;
2325
import org.springframework.data.relational.core.mapping.PersistentPropertyPathExtension;
26+
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
2427
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
2528
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
2629
import org.springframework.data.util.TypeInformation;
@@ -67,8 +70,24 @@ public interface JdbcConverter extends RelationalConverter {
6770
* @param key primary key.
6871
* @param <T>
6972
* @return
73+
* @deprecated use {@link #mapRow(AggregatePath, ResultSet, Identifier, Object)} instead.
7074
*/
71-
<T> T mapRow(PersistentPropertyPathExtension path, ResultSet resultSet, Identifier identifier, Object key);
75+
@Deprecated(since = "3.2", forRemoval = true)
76+
default <T> T mapRow(PersistentPropertyPathExtension path, ResultSet resultSet, Identifier identifier, Object key){
77+
return mapRow(path.getAggregatePath(), resultSet, identifier, key);
78+
};
79+
80+
/**
81+
* Read the current row from {@link ResultSet} to an {@link AggregatePath#getLeafEntity()} entity}.
82+
*
83+
* @param path path to the owning property.
84+
* @param resultSet the {@link ResultSet} to read from.
85+
* @param identifier entity identifier.
86+
* @param key primary key.
87+
* @param <T>
88+
* @return
89+
*/
90+
<T> T mapRow(AggregatePath path, ResultSet resultSet, Identifier identifier, Object key);
7291

7392
/**
7493
* The type to be used to store this property in the database. Multidimensional arrays are unwrapped to reflect a
@@ -88,4 +107,7 @@ public interface JdbcConverter extends RelationalConverter {
88107
* @since 2.0
89108
*/
90109
SQLType getTargetSqlType(RelationalPersistentProperty property);
110+
111+
@Override
112+
RelationalMappingContext getMappingContext();
91113
}

0 commit comments

Comments
 (0)