15
15
*/
16
16
package org .springframework .data .jdbc .core .convert ;
17
17
18
+ import java .sql .ResultSet ;
19
+ import java .sql .SQLException ;
18
20
import java .util .ArrayList ;
19
21
import java .util .Iterator ;
20
22
import java .util .List ;
27
29
import org .springframework .data .relational .core .sqlgeneration .AliasFactory ;
28
30
import org .springframework .data .relational .core .sqlgeneration .SingleQuerySqlGenerator ;
29
31
import org .springframework .data .relational .core .sqlgeneration .SqlGenerator ;
32
+ import org .springframework .data .relational .domain .RowDocument ;
30
33
import org .springframework .jdbc .core .namedparam .NamedParameterJdbcOperations ;
31
34
import org .springframework .lang .Nullable ;
32
35
import org .springframework .util .Assert ;
33
36
34
37
/**
35
38
* 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)}.
38
42
*
39
43
* @param <T> the type of aggregate produced by this reader.
40
44
* @author Jens Schauder
45
+ * @author Mark Paluch
41
46
* @since 3.2
42
47
*/
43
48
class AggregateReader <T > {
44
49
45
- private final RelationalPersistentEntity <T > aggregate ;
50
+ private final RelationalPersistentEntity <T > entity ;
46
51
private final org .springframework .data .relational .core .sqlgeneration .SqlGenerator sqlGenerator ;
47
52
private final JdbcConverter converter ;
48
53
private final NamedParameterJdbcOperations jdbcTemplate ;
49
- private final AggregateResultSetExtractor < T > extractor ;
54
+ private final ResultSetRowDocumentExtractor extractor ;
50
55
51
56
AggregateReader (Dialect dialect , JdbcConverter converter , AliasFactory aliasFactory ,
52
- NamedParameterJdbcOperations jdbcTemplate , RelationalPersistentEntity <T > aggregate ) {
57
+ NamedParameterJdbcOperations jdbcTemplate , RelationalPersistentEntity <T > entity ) {
53
58
54
59
this .converter = converter ;
55
- this .aggregate = aggregate ;
60
+ this .entity = entity ;
56
61
this .jdbcTemplate = jdbcTemplate ;
57
62
58
63
this .sqlGenerator = new CachingSqlGenerator (
59
- new SingleQuerySqlGenerator (converter .getMappingContext (), aliasFactory , dialect , aggregate ));
64
+ new SingleQuerySqlGenerator (converter .getMappingContext (), aliasFactory , dialect , entity ));
60
65
61
- this .extractor = new AggregateResultSetExtractor <>(aggregate , converter , createPathToColumnMapping (aliasFactory ));
66
+ this .extractor = new ResultSetRowDocumentExtractor (converter .getMappingContext (),
67
+ createPathToColumnMapping (aliasFactory ));
62
68
}
63
69
64
70
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 );
71
72
}
72
73
73
74
@ Nullable
74
75
public T findById (Object id ) {
75
76
76
- id = converter .writeValue (id , aggregate .getRequiredIdProperty ().getTypeInformation ());
77
+ id = converter .writeValue (id , entity .getRequiredIdProperty ().getTypeInformation ());
77
78
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 -> {
79
80
80
- T returnValue = result .hasNext () ? result .next () : null ;
81
+ Iterator <RowDocument > iterate = extractor .iterate (entity , rs );
82
+ if (iterate .hasNext ()) {
81
83
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
+ });
87
92
}
88
93
89
94
public Iterable <T > findAllById (Iterable <?> ids ) {
90
95
91
96
List <Object > convertedIds = new ArrayList <>();
92
97
for (Object id : ids ) {
93
- convertedIds .add (converter .writeValue (id , aggregate .getRequiredIdProperty ().getTypeInformation ()));
98
+ convertedIds .add (converter .writeValue (id , entity .getRequiredIdProperty ().getTypeInformation ()));
94
99
}
95
100
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 ;
97
113
}
98
114
99
115
private PathToColumnMapping createPathToColumnMapping (AliasFactory aliasFactory ) {
@@ -117,8 +133,8 @@ public String keyColumn(AggregatePath path) {
117
133
* A wrapper for the {@link org.springframework.data.relational.core.sqlgeneration.SqlGenerator} that caches the
118
134
* generated statements.
119
135
*
120
- * @since 3.2
121
136
* @author Jens Schauder
137
+ * @since 3.2
122
138
*/
123
139
static class CachingSqlGenerator implements org .springframework .data .relational .core .sqlgeneration .SqlGenerator {
124
140
0 commit comments