1515 */
1616package org .springframework .data .jdbc .core .convert ;
1717
18+ import java .sql .ResultSet ;
19+ import java .sql .SQLException ;
1820import java .util .ArrayList ;
1921import java .util .Iterator ;
2022import java .util .List ;
2729import org .springframework .data .relational .core .sqlgeneration .AliasFactory ;
2830import org .springframework .data .relational .core .sqlgeneration .SingleQuerySqlGenerator ;
2931import org .springframework .data .relational .core .sqlgeneration .SqlGenerator ;
32+ import org .springframework .data .relational .domain .RowDocument ;
3033import org .springframework .jdbc .core .namedparam .NamedParameterJdbcOperations ;
3134import org .springframework .lang .Nullable ;
3235import org .springframework .util .Assert ;
3336
3437/**
3538 * Reads complete Aggregates from the database, by generating appropriate SQL using a {@link SingleQuerySqlGenerator}
36- * and a matching {@link AggregateResultSetExtractor} and invoking a
37- * {@link org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate}
39+ * through {@link org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate}. Results are converterd into an
40+ * intermediate {@link ResultSetRowDocumentExtractor RowDocument} and mapped via
41+ * {@link org.springframework.data.relational.core.conversion.RelationalConverter#read(Class, RowDocument)}.
3842 *
3943 * @param <T> the type of aggregate produced by this reader.
4044 * @author Jens Schauder
45+ * @author Mark Paluch
4146 * @since 3.2
4247 */
4348class AggregateReader <T > {
4449
45- private final RelationalPersistentEntity <T > aggregate ;
50+ private final RelationalPersistentEntity <T > entity ;
4651 private final org .springframework .data .relational .core .sqlgeneration .SqlGenerator sqlGenerator ;
4752 private final JdbcConverter converter ;
4853 private final NamedParameterJdbcOperations jdbcTemplate ;
49- private final AggregateResultSetExtractor < T > extractor ;
54+ private final ResultSetRowDocumentExtractor extractor ;
5055
5156 AggregateReader (Dialect dialect , JdbcConverter converter , AliasFactory aliasFactory ,
52- NamedParameterJdbcOperations jdbcTemplate , RelationalPersistentEntity <T > aggregate ) {
57+ NamedParameterJdbcOperations jdbcTemplate , RelationalPersistentEntity <T > entity ) {
5358
5459 this .converter = converter ;
55- this .aggregate = aggregate ;
60+ this .entity = entity ;
5661 this .jdbcTemplate = jdbcTemplate ;
5762
5863 this .sqlGenerator = new CachingSqlGenerator (
59- new SingleQuerySqlGenerator (converter .getMappingContext (), aliasFactory , dialect , aggregate ));
64+ new SingleQuerySqlGenerator (converter .getMappingContext (), aliasFactory , dialect , entity ));
6065
61- this .extractor = new AggregateResultSetExtractor <>(aggregate , converter , createPathToColumnMapping (aliasFactory ));
66+ this .extractor = new ResultSetRowDocumentExtractor (converter .getMappingContext (),
67+ createPathToColumnMapping (aliasFactory ));
6268 }
6369
6470 public List <T > findAll () {
65-
66- Iterable <T > result = jdbcTemplate .query (sqlGenerator .findAll (), extractor );
67-
68- Assert .state (result != null , "result is null" );
69-
70- return (List <T >) result ;
71+ return jdbcTemplate .query (sqlGenerator .findAll (), this ::extractAll );
7172 }
7273
7374 @ Nullable
7475 public T findById (Object id ) {
7576
76- id = converter .writeValue (id , aggregate .getRequiredIdProperty ().getTypeInformation ());
77+ id = converter .writeValue (id , entity .getRequiredIdProperty ().getTypeInformation ());
7778
78- Iterator < T > result = jdbcTemplate .query (sqlGenerator .findById (), Map .of ("id" , id ), extractor ). iterator ();
79+ return jdbcTemplate .query (sqlGenerator .findById (), Map .of ("id" , id ), rs -> {
7980
80- T returnValue = result .hasNext () ? result .next () : null ;
81+ Iterator <RowDocument > iterate = extractor .iterate (entity , rs );
82+ if (iterate .hasNext ()) {
8183
82- if (result .hasNext ()) {
83- throw new IncorrectResultSizeDataAccessException (1 );
84- }
85-
86- return returnValue ;
84+ RowDocument object = iterate .next ();
85+ if (iterate .hasNext ()) {
86+ throw new IncorrectResultSizeDataAccessException (1 );
87+ }
88+ return converter .read (entity .getType (), object );
89+ }
90+ return null ;
91+ });
8792 }
8893
8994 public Iterable <T > findAllById (Iterable <?> ids ) {
9095
9196 List <Object > convertedIds = new ArrayList <>();
9297 for (Object id : ids ) {
93- convertedIds .add (converter .writeValue (id , aggregate .getRequiredIdProperty ().getTypeInformation ()));
98+ convertedIds .add (converter .writeValue (id , entity .getRequiredIdProperty ().getTypeInformation ()));
9499 }
95100
96- return jdbcTemplate .query (sqlGenerator .findAllById (), Map .of ("ids" , convertedIds ), extractor );
101+ return jdbcTemplate .query (sqlGenerator .findAllById (), Map .of ("ids" , convertedIds ), this ::extractAll );
102+ }
103+
104+ private List <T > extractAll (ResultSet rs ) throws SQLException {
105+
106+ Iterator <RowDocument > iterate = extractor .iterate (entity , rs );
107+ List <T > resultList = new ArrayList <>();
108+ while (iterate .hasNext ()) {
109+ resultList .add (converter .read (entity .getType (), iterate .next ()));
110+ }
111+
112+ return resultList ;
97113 }
98114
99115 private PathToColumnMapping createPathToColumnMapping (AliasFactory aliasFactory ) {
@@ -117,8 +133,8 @@ public String keyColumn(AggregatePath path) {
117133 * A wrapper for the {@link org.springframework.data.relational.core.sqlgeneration.SqlGenerator} that caches the
118134 * generated statements.
119135 *
120- * @since 3.2
121136 * @author Jens Schauder
137+ * @since 3.2
122138 */
123139 static class CachingSqlGenerator implements org .springframework .data .relational .core .sqlgeneration .SqlGenerator {
124140
0 commit comments