48
48
* intermediate {@link RowDocumentResultSetExtractor RowDocument} and mapped via
49
49
* {@link org.springframework.data.relational.core.conversion.RelationalConverter#read(Class, RowDocument)}.
50
50
*
51
- * @param <T> the type of aggregate produced by this reader.
52
51
* @author Jens Schauder
53
52
* @author Mark Paluch
54
53
* @since 3.2
55
54
*/
56
- class AggregateReader < T > implements PathToColumnMapping {
55
+ class AggregateReader implements PathToColumnMapping {
57
56
58
- private final RelationalPersistentEntity <T > aggregate ;
59
- private final Table table ;
57
+ private final AliasFactory aliasFactory ;
60
58
private final SqlGenerator sqlGenerator ;
61
59
private final JdbcConverter converter ;
62
60
private final NamedParameterJdbcOperations jdbcTemplate ;
63
- private final AliasFactory aliasFactory ;
64
61
private final RowDocumentResultSetExtractor extractor ;
65
62
66
- AggregateReader (Dialect dialect , JdbcConverter converter , AliasFactory aliasFactory ,
67
- NamedParameterJdbcOperations jdbcTemplate , RelationalPersistentEntity <T > aggregate ) {
63
+ AggregateReader (Dialect dialect , JdbcConverter converter , NamedParameterJdbcOperations jdbcTemplate ) {
68
64
65
+ this .aliasFactory = new AliasFactory ();
69
66
this .converter = converter ;
70
- this .aggregate = aggregate ;
71
67
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 );
75
69
this .extractor = new RowDocumentResultSetExtractor (converter .getMappingContext (), this );
76
70
}
77
71
@@ -92,55 +86,96 @@ public String keyColumn(AggregatePath path) {
92
86
return aliasFactory .getKeyAlias (path );
93
87
}
94
88
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
+ */
95
97
@ Nullable
96
- public T findById (Object id ) {
98
+ public < T > T findById (Object id , RelationalPersistentEntity < T > entity ) {
97
99
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 );
99
101
100
- return findOne (query );
102
+ return findOne (query , entity );
101
103
}
102
104
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
+ */
103
113
@ 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 ) );
106
116
}
107
117
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 ) {
109
128
110
129
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 ));
112
131
113
- return findAll (query );
132
+ return findAll (query , entity );
114
133
}
115
134
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
+ */
116
142
@ 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 ));
119
146
}
120
147
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 ));
123
158
}
124
159
125
160
@ 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 ) {
127
162
128
163
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 );
131
166
132
167
return jdbcTemplate .query (sql , parameterSource , extractor );
133
168
}
134
169
135
170
@ Nullable
136
- private Condition createCondition (Query query , MapSqlParameterSource parameterSource ) {
171
+ private Condition createCondition (Query query , MapSqlParameterSource parameterSource ,
172
+ RelationalPersistentEntity <?> entity ) {
137
173
138
174
QueryMapper queryMapper = new QueryMapper (converter );
139
175
140
176
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 );
144
179
}
145
180
146
181
/**
@@ -152,12 +187,13 @@ private Condition createCondition(Query query, MapSqlParameterSource parameterSo
152
187
* @return a {@code List} of aggregates, fully converted.
153
188
* @throws SQLException on underlying JDBC errors.
154
189
*/
155
- private List <T > extractAll (ResultSet rs ) throws SQLException {
190
+ private < T > List <T > extractAll (ResultSet rs , RelationalPersistentEntity < T > entity ) throws SQLException {
156
191
157
- Iterator <RowDocument > iterate = extractor .iterate (aggregate , rs );
192
+ Iterator <RowDocument > iterate = extractor .iterate (entity , rs );
158
193
List <T > resultList = new ArrayList <>();
194
+
159
195
while (iterate .hasNext ()) {
160
- resultList .add (converter .read (aggregate .getType (), iterate .next ()));
196
+ resultList .add (converter .read (entity .getType (), iterate .next ()));
161
197
}
162
198
163
199
return resultList ;
@@ -175,17 +211,19 @@ private List<T> extractAll(ResultSet rs) throws SQLException {
175
211
* @throws IncorrectResultSizeDataAccessException when the conversion yields more than one instance.
176
212
*/
177
213
@ 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 );
179
217
180
- Iterator <RowDocument > iterate = extractor .iterate (aggregate , rs );
181
218
if (iterate .hasNext ()) {
182
219
183
220
RowDocument object = iterate .next ();
184
221
if (iterate .hasNext ()) {
185
222
throw new IncorrectResultSizeDataAccessException (1 );
186
223
}
187
- return converter .read (aggregate .getType (), object );
224
+ return converter .read (entity .getType (), object );
188
225
}
226
+
189
227
return null ;
190
228
}
191
229
0 commit comments