Skip to content

Commit a555119

Browse files
committed
Polishing.
Remove Jetbrains annotation usage. Simplify code, remove code that is commented out, extract methods, pass PersistentEntity as argument instead of creating instances that hold PersistentEntity as field to align the class lifecycle with its contextual usage. Refactor AggregateReader lifecycle, use a single instance as there is no entity-specific state attached to AggregateReader. Add Javadoc. See #1448 Original pull request: #1622
1 parent 9e795d1 commit a555119

File tree

10 files changed

+237
-262
lines changed

10 files changed

+237
-262
lines changed

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

+74-36
Original file line numberDiff line numberDiff line change
@@ -48,30 +48,24 @@
4848
* intermediate {@link RowDocumentResultSetExtractor RowDocument} and mapped via
4949
* {@link org.springframework.data.relational.core.conversion.RelationalConverter#read(Class, RowDocument)}.
5050
*
51-
* @param <T> the type of aggregate produced by this reader.
5251
* @author Jens Schauder
5352
* @author Mark Paluch
5453
* @since 3.2
5554
*/
56-
class AggregateReader<T> implements PathToColumnMapping {
55+
class AggregateReader implements PathToColumnMapping {
5756

58-
private final RelationalPersistentEntity<T> aggregate;
59-
private final Table table;
57+
private final AliasFactory aliasFactory;
6058
private final SqlGenerator sqlGenerator;
6159
private final JdbcConverter converter;
6260
private final NamedParameterJdbcOperations jdbcTemplate;
63-
private final AliasFactory aliasFactory;
6461
private final RowDocumentResultSetExtractor extractor;
6562

66-
AggregateReader(Dialect dialect, JdbcConverter converter, AliasFactory aliasFactory,
67-
NamedParameterJdbcOperations jdbcTemplate, RelationalPersistentEntity<T> aggregate) {
63+
AggregateReader(Dialect dialect, JdbcConverter converter, NamedParameterJdbcOperations jdbcTemplate) {
6864

65+
this.aliasFactory = new AliasFactory();
6966
this.converter = converter;
70-
this.aggregate = aggregate;
7167
this.jdbcTemplate = jdbcTemplate;
72-
this.table = Table.create(aggregate.getQualifiedTableName());
73-
this.sqlGenerator = new SingleQuerySqlGenerator(converter.getMappingContext(), aliasFactory, dialect, aggregate);
74-
this.aliasFactory = aliasFactory;
68+
this.sqlGenerator = new SingleQuerySqlGenerator(converter.getMappingContext(), aliasFactory, dialect);
7569
this.extractor = new RowDocumentResultSetExtractor(converter.getMappingContext(), this);
7670
}
7771

@@ -92,55 +86,96 @@ public String keyColumn(AggregatePath path) {
9286
return aliasFactory.getKeyAlias(path);
9387
}
9488

89+
/**
90+
* Select a single aggregate by its identifier.
91+
*
92+
* @param id the identifier, must not be {@literal null}.
93+
* @param entity the persistent entity type must not be {@literal null}.
94+
* @return the found aggregate root, or {@literal null} if not found.
95+
* @param <T> aggregator type.
96+
*/
9597
@Nullable
96-
public T findById(Object id) {
98+
public <T> T findById(Object id, RelationalPersistentEntity<T> entity) {
9799

98-
Query query = Query.query(Criteria.where(aggregate.getRequiredIdProperty().getName()).is(id)).limit(1);
100+
Query query = Query.query(Criteria.where(entity.getRequiredIdProperty().getName()).is(id)).limit(1);
99101

100-
return findOne(query);
102+
return findOne(query, entity);
101103
}
102104

105+
/**
106+
* Select a single aggregate by a {@link Query}.
107+
*
108+
* @param query the query to run, must not be {@literal null}.
109+
* @param entity the persistent entity type must not be {@literal null}.
110+
* @return the found aggregate root, or {@literal null} if not found.
111+
* @param <T> aggregator type.
112+
*/
103113
@Nullable
104-
public T findOne(Query query) {
105-
return doFind(query, this::extractZeroOrOne);
114+
public <T> T findOne(Query query, RelationalPersistentEntity<T> entity) {
115+
return doFind(query, entity, rs -> extractZeroOrOne(rs, entity));
106116
}
107117

108-
public List<T> findAllById(Iterable<?> ids) {
118+
/**
119+
* Select aggregates by their identifiers.
120+
*
121+
* @param ids the identifiers, must not be {@literal null}.
122+
* @param entity the persistent entity type must not be {@literal null}.
123+
* @return the found aggregate roots. The resulting list can be empty or may not contain objects that correspond to
124+
* the identifiers when the objects are not found in the database.
125+
* @param <T> aggregator type.
126+
*/
127+
public <T> List<T> findAllById(Iterable<?> ids, RelationalPersistentEntity<T> entity) {
109128

110129
Collection<?> identifiers = ids instanceof Collection<?> idl ? idl : Streamable.of(ids).toList();
111-
Query query = Query.query(Criteria.where(aggregate.getRequiredIdProperty().getName()).in(identifiers));
130+
Query query = Query.query(Criteria.where(entity.getRequiredIdProperty().getName()).in(identifiers));
112131

113-
return findAll(query);
132+
return findAll(query, entity);
114133
}
115134

135+
/**
136+
* Select all aggregates by type.
137+
*
138+
* @param entity the persistent entity type must not be {@literal null}.
139+
* @return the found aggregate roots.
140+
* @param <T> aggregator type.
141+
*/
116142
@SuppressWarnings("ConstantConditions")
117-
public List<T> findAll() {
118-
return jdbcTemplate.query(sqlGenerator.findAll(), this::extractAll);
143+
public <T> List<T> findAll(RelationalPersistentEntity<T> entity) {
144+
return jdbcTemplate.query(sqlGenerator.findAll(entity),
145+
(ResultSetExtractor<? extends List<T>>) rs -> extractAll(rs, entity));
119146
}
120147

121-
public List<T> findAll(Query query) {
122-
return doFind(query, this::extractAll);
148+
/**
149+
* Select all aggregates by query.
150+
*
151+
* @param query the query to run, must not be {@literal null}.
152+
* @param entity the persistent entity type must not be {@literal null}.
153+
* @return the found aggregate roots.
154+
* @param <T> aggregator type.
155+
*/
156+
public <T> List<T> findAll(Query query, RelationalPersistentEntity<T> entity) {
157+
return doFind(query, entity, rs -> extractAll(rs, entity));
123158
}
124159

125160
@SuppressWarnings("ConstantConditions")
126-
private <R> R doFind(Query query, ResultSetExtractor<R> extractor) {
161+
private <T, R> R doFind(Query query, RelationalPersistentEntity<T> entity, ResultSetExtractor<R> extractor) {
127162

128163
MapSqlParameterSource parameterSource = new MapSqlParameterSource();
129-
Condition condition = createCondition(query, parameterSource);
130-
String sql = sqlGenerator.findAll(condition);
164+
Condition condition = createCondition(query, parameterSource, entity);
165+
String sql = sqlGenerator.findAll(entity, condition);
131166

132167
return jdbcTemplate.query(sql, parameterSource, extractor);
133168
}
134169

135170
@Nullable
136-
private Condition createCondition(Query query, MapSqlParameterSource parameterSource) {
171+
private Condition createCondition(Query query, MapSqlParameterSource parameterSource,
172+
RelationalPersistentEntity<?> entity) {
137173

138174
QueryMapper queryMapper = new QueryMapper(converter);
139175

140176
Optional<CriteriaDefinition> criteria = query.getCriteria();
141-
return criteria
142-
.map(criteriaDefinition -> queryMapper.getMappedObject(parameterSource, criteriaDefinition, table, aggregate))
143-
.orElse(null);
177+
return criteria.map(criteriaDefinition -> queryMapper.getMappedObject(parameterSource, criteriaDefinition,
178+
Table.create(entity.getQualifiedTableName()), entity)).orElse(null);
144179
}
145180

146181
/**
@@ -152,12 +187,13 @@ private Condition createCondition(Query query, MapSqlParameterSource parameterSo
152187
* @return a {@code List} of aggregates, fully converted.
153188
* @throws SQLException on underlying JDBC errors.
154189
*/
155-
private List<T> extractAll(ResultSet rs) throws SQLException {
190+
private <T> List<T> extractAll(ResultSet rs, RelationalPersistentEntity<T> entity) throws SQLException {
156191

157-
Iterator<RowDocument> iterate = extractor.iterate(aggregate, rs);
192+
Iterator<RowDocument> iterate = extractor.iterate(entity, rs);
158193
List<T> resultList = new ArrayList<>();
194+
159195
while (iterate.hasNext()) {
160-
resultList.add(converter.read(aggregate.getType(), iterate.next()));
196+
resultList.add(converter.read(entity.getType(), iterate.next()));
161197
}
162198

163199
return resultList;
@@ -175,17 +211,19 @@ private List<T> extractAll(ResultSet rs) throws SQLException {
175211
* @throws IncorrectResultSizeDataAccessException when the conversion yields more than one instance.
176212
*/
177213
@Nullable
178-
private T extractZeroOrOne(ResultSet rs) throws SQLException {
214+
private <T> T extractZeroOrOne(ResultSet rs, RelationalPersistentEntity<T> entity) throws SQLException {
215+
216+
Iterator<RowDocument> iterate = extractor.iterate(entity, rs);
179217

180-
Iterator<RowDocument> iterate = extractor.iterate(aggregate, rs);
181218
if (iterate.hasNext()) {
182219

183220
RowDocument object = iterate.next();
184221
if (iterate.hasNext()) {
185222
throw new IncorrectResultSizeDataAccessException(1);
186223
}
187-
return converter.read(aggregate.getType(), object);
224+
return converter.read(entity.getType(), object);
188225
}
226+
189227
return null;
190228
}
191229

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

+9-18
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,7 @@
2525
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
2626
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
2727
import org.springframework.data.relational.core.query.Query;
28-
import org.springframework.data.relational.core.sqlgeneration.AliasFactory;
2928
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
30-
import org.springframework.util.ConcurrentLruCache;
3129

3230
/**
3331
* A {@link ReadingDataAccessStrategy} that uses an {@link AggregateReader} to load entities with a single query.
@@ -39,31 +37,28 @@
3937
class SingleQueryDataAccessStrategy implements ReadingDataAccessStrategy {
4038

4139
private final RelationalMappingContext mappingContext;
42-
private final AliasFactory aliasFactory;
43-
private final ConcurrentLruCache<RelationalPersistentEntity<?>, AggregateReader<?>> readerCache;
40+
private final AggregateReader aggregateReader;
4441

4542
public SingleQueryDataAccessStrategy(Dialect dialect, JdbcConverter converter,
4643
NamedParameterJdbcOperations jdbcTemplate) {
4744

4845
this.mappingContext = converter.getMappingContext();
49-
this.aliasFactory = new AliasFactory();
50-
this.readerCache = new ConcurrentLruCache<>(256,
51-
entity -> new AggregateReader<>(dialect, converter, aliasFactory, jdbcTemplate, entity));
46+
this.aggregateReader = new AggregateReader(dialect, converter, jdbcTemplate);
5247
}
5348

5449
@Override
5550
public <T> T findById(Object id, Class<T> domainType) {
56-
return getReader(domainType).findById(id);
51+
return aggregateReader.findById(id, getPersistentEntity(domainType));
5752
}
5853

5954
@Override
6055
public <T> List<T> findAll(Class<T> domainType) {
61-
return getReader(domainType).findAll();
56+
return aggregateReader.findAll(getPersistentEntity(domainType));
6257
}
6358

6459
@Override
6560
public <T> List<T> findAllById(Iterable<?> ids, Class<T> domainType) {
66-
return getReader(domainType).findAllById(ids);
61+
return aggregateReader.findAllById(ids, getPersistentEntity(domainType));
6762
}
6863

6964
@Override
@@ -78,12 +73,12 @@ public <T> List<T> findAll(Class<T> domainType, Pageable pageable) {
7873

7974
@Override
8075
public <T> Optional<T> findOne(Query query, Class<T> domainType) {
81-
return Optional.ofNullable(getReader(domainType).findOne(query));
76+
return Optional.ofNullable(aggregateReader.findOne(query, getPersistentEntity(domainType)));
8277
}
8378

8479
@Override
8580
public <T> List<T> findAll(Query query, Class<T> domainType) {
86-
return getReader(domainType).findAll(query);
81+
return aggregateReader.findAll(query, getPersistentEntity(domainType));
8782
}
8883

8984
@Override
@@ -92,11 +87,7 @@ public <T> List<T> findAll(Query query, Class<T> domainType, Pageable pageable)
9287
}
9388

9489
@SuppressWarnings("unchecked")
95-
private <T> AggregateReader<T> getReader(Class<T> domainType) {
96-
97-
RelationalPersistentEntity<T> persistentEntity = (RelationalPersistentEntity<T>) mappingContext
98-
.getRequiredPersistentEntity(domainType);
99-
100-
return (AggregateReader<T>) readerCache.get(persistentEntity);
90+
private <T> RelationalPersistentEntity<T> getPersistentEntity(Class<T> domainType) {
91+
return (RelationalPersistentEntity<T>) mappingContext.getRequiredPersistentEntity(domainType);
10192
}
10293
}

0 commit comments

Comments
 (0)