18
18
import reactor .core .publisher .Flux ;
19
19
import reactor .core .publisher .Mono ;
20
20
21
- import java .util .Collections ;
22
- import java .util .List ;
23
-
24
21
import org .reactivestreams .Publisher ;
25
22
26
- import org .springframework .dao .TransientDataAccessResourceException ;
27
23
import org .springframework .data .r2dbc .convert .R2dbcConverter ;
28
24
import org .springframework .data .r2dbc .core .DatabaseClient ;
29
- import org .springframework .data .r2dbc .core .PreparedOperation ;
25
+ import org .springframework .data .r2dbc .core .R2dbcEntityOperations ;
26
+ import org .springframework .data .r2dbc .core .R2dbcEntityTemplate ;
30
27
import org .springframework .data .r2dbc .core .ReactiveDataAccessStrategy ;
31
- import org .springframework .data .r2dbc .core .StatementMapper ;
32
28
import org .springframework .data .r2dbc .query .Criteria ;
29
+ import org .springframework .data .r2dbc .query .Query ;
33
30
import org .springframework .data .relational .core .mapping .RelationalPersistentProperty ;
34
- import org .springframework .data .relational .core .sql .Functions ;
35
- import org .springframework .data .relational .core .sql .Select ;
36
- import org .springframework .data .relational .core .sql .StatementBuilder ;
37
- import org .springframework .data .relational .core .sql .Table ;
38
- import org .springframework .data .relational .core .sql .render .SqlRenderer ;
39
31
import org .springframework .data .relational .repository .query .RelationalEntityInformation ;
40
32
import org .springframework .data .repository .reactive .ReactiveCrudRepository ;
33
+ import org .springframework .data .util .Lazy ;
41
34
import org .springframework .transaction .annotation .Transactional ;
42
35
import org .springframework .util .Assert ;
43
36
51
44
public class SimpleR2dbcRepository <T , ID > implements ReactiveCrudRepository <T , ID > {
52
45
53
46
private final RelationalEntityInformation <T , ID > entity ;
54
- private final DatabaseClient databaseClient ;
55
- private final R2dbcConverter converter ;
56
- private final ReactiveDataAccessStrategy accessStrategy ;
47
+ private final R2dbcEntityOperations entityOperations ;
48
+ private final Lazy <RelationalPersistentProperty > idProperty ;
49
+
50
+ /**
51
+ * Create a new {@link SimpleR2dbcRepository}.
52
+ *
53
+ * @param entity
54
+ * @param entityOperations
55
+ * @param converter
56
+ * @since 1.1
57
+ */
58
+ SimpleR2dbcRepository (RelationalEntityInformation <T , ID > entity , R2dbcEntityOperations entityOperations ,
59
+ R2dbcConverter converter ) {
60
+
61
+ this .entity = entity ;
62
+ this .entityOperations = entityOperations ;
63
+ this .idProperty = Lazy .of (() -> converter //
64
+ .getMappingContext () //
65
+ .getRequiredPersistentEntity (this .entity .getJavaType ()) //
66
+ .getRequiredIdProperty ());
67
+ }
57
68
69
+ /**
70
+ * Create a new {@link SimpleR2dbcRepository}.
71
+ *
72
+ * @param entity
73
+ * @param databaseClient
74
+ * @param converter
75
+ * @param accessStrategy
76
+ */
58
77
public SimpleR2dbcRepository (RelationalEntityInformation <T , ID > entity , DatabaseClient databaseClient ,
59
78
R2dbcConverter converter , ReactiveDataAccessStrategy accessStrategy ) {
79
+
60
80
this .entity = entity ;
61
- this .databaseClient = databaseClient ;
62
- this .converter = converter ;
63
- this .accessStrategy = accessStrategy ;
81
+ this .entityOperations = new R2dbcEntityTemplate (databaseClient );
82
+ this .idProperty = Lazy .of (() -> converter //
83
+ .getMappingContext () //
84
+ .getRequiredPersistentEntity (this .entity .getJavaType ()) //
85
+ .getRequiredIdProperty ());
64
86
}
65
87
66
88
/* (non-Javadoc)
@@ -73,28 +95,10 @@ public <S extends T> Mono<S> save(S objectToSave) {
73
95
Assert .notNull (objectToSave , "Object to save must not be null!" );
74
96
75
97
if (this .entity .isNew (objectToSave )) {
76
-
77
- return this .databaseClient .insert () //
78
- .into (this .entity .getJavaType ()) //
79
- .table (this .entity .getTableName ()).using (objectToSave ) //
80
- .map (this .converter .populateIdIfNecessary (objectToSave )) //
81
- .first () //
82
- .defaultIfEmpty (objectToSave );
98
+ return this .entityOperations .insert (objectToSave );
83
99
}
84
100
85
- return this .databaseClient .update () //
86
- .table (this .entity .getJavaType ()) //
87
- .table (this .entity .getTableName ()).using (objectToSave ) //
88
- .fetch ().rowsUpdated ().handle ((rowsUpdated , sink ) -> {
89
-
90
- if (rowsUpdated == 0 ) {
91
- sink .error (new TransientDataAccessResourceException (
92
- String .format ("Failed to update table [%s]. Row with Id [%s] does not exist." ,
93
- this .entity .getTableName (), this .entity .getId (objectToSave ))));
94
- } else {
95
- sink .next (objectToSave );
96
- }
97
- });
101
+ return this .entityOperations .update (objectToSave );
98
102
}
99
103
100
104
/* (non-Javadoc)
@@ -129,20 +133,7 @@ public Mono<T> findById(ID id) {
129
133
130
134
Assert .notNull (id , "Id must not be null!" );
131
135
132
- List <String > columns = this .accessStrategy .getAllColumns (this .entity .getJavaType ());
133
- String idProperty = getIdProperty ().getName ();
134
-
135
- StatementMapper mapper = this .accessStrategy .getStatementMapper ().forType (this .entity .getJavaType ());
136
- StatementMapper .SelectSpec selectSpec = mapper .createSelect (this .entity .getTableName ()) //
137
- .withProjection (columns ) //
138
- .withCriteria (Criteria .where (idProperty ).is (id ));
139
-
140
- PreparedOperation <?> operation = mapper .getMappedObject (selectSpec );
141
-
142
- return this .databaseClient .execute (operation ) //
143
- .as (this .entity .getJavaType ()) //
144
- .fetch () //
145
- .one ();
136
+ return this .entityOperations .selectOne (getIdQuery (id ), this .entity .getJavaType ());
146
137
}
147
138
148
139
/* (non-Javadoc)
@@ -161,19 +152,7 @@ public Mono<Boolean> existsById(ID id) {
161
152
162
153
Assert .notNull (id , "Id must not be null!" );
163
154
164
- String idProperty = getIdProperty ().getName ();
165
-
166
- StatementMapper mapper = this .accessStrategy .getStatementMapper ().forType (this .entity .getJavaType ());
167
- StatementMapper .SelectSpec selectSpec = mapper .createSelect (this .entity .getTableName ())
168
- .withProjection (Collections .singletonList (idProperty )) //
169
- .withCriteria (Criteria .where (idProperty ).is (id ));
170
-
171
- PreparedOperation <?> operation = mapper .getMappedObject (selectSpec );
172
-
173
- return this .databaseClient .execute (operation ) //
174
- .map ((r , md ) -> r ) //
175
- .first () //
176
- .hasElement ();
155
+ return this .entityOperations .exists (getIdQuery (id ), this .entity .getJavaType ());
177
156
}
178
157
179
158
/* (non-Javadoc)
@@ -189,7 +168,7 @@ public Mono<Boolean> existsById(Publisher<ID> publisher) {
189
168
*/
190
169
@ Override
191
170
public Flux <T > findAll () {
192
- return this .databaseClient .select (). from ( this .entity .getJavaType ()). fetch (). all ( );
171
+ return this .entityOperations .select (Query . empty (), this .entity .getJavaType ());
193
172
}
194
173
195
174
/* (non-Javadoc)
@@ -217,17 +196,9 @@ public Flux<T> findAllById(Publisher<ID> idPublisher) {
217
196
return Flux .empty ();
218
197
}
219
198
220
- List <String > columns = this .accessStrategy .getAllColumns (this .entity .getJavaType ());
221
199
String idProperty = getIdProperty ().getName ();
222
200
223
- StatementMapper mapper = this .accessStrategy .getStatementMapper ().forType (this .entity .getJavaType ());
224
- StatementMapper .SelectSpec selectSpec = mapper .createSelect (this .entity .getTableName ()) //
225
- .withProjection (columns ) //
226
- .withCriteria (Criteria .where (idProperty ).in (ids ));
227
-
228
- PreparedOperation <?> operation = mapper .getMappedObject (selectSpec );
229
-
230
- return this .databaseClient .execute (operation ).as (this .entity .getJavaType ()).fetch ().all ();
201
+ return this .entityOperations .select (Query .query (Criteria .where (idProperty ).in (ids )), this .entity .getJavaType ());
231
202
});
232
203
}
233
204
@@ -236,17 +207,7 @@ public Flux<T> findAllById(Publisher<ID> idPublisher) {
236
207
*/
237
208
@ Override
238
209
public Mono <Long > count () {
239
-
240
- Table table = Table .create (this .entity .getTableName ());
241
- Select select = StatementBuilder //
242
- .select (Functions .count (table .column (getIdProperty ().getColumnName ()))) //
243
- .from (table ) //
244
- .build ();
245
-
246
- return this .databaseClient .execute (SqlRenderer .toString (select )) //
247
- .map ((r , md ) -> r .get (0 , Long .class )) //
248
- .first () //
249
- .defaultIfEmpty (0L );
210
+ return this .entityOperations .count (Query .empty (), this .entity .getJavaType ());
250
211
}
251
212
252
213
/* (non-Javadoc)
@@ -258,13 +219,7 @@ public Mono<Void> deleteById(ID id) {
258
219
259
220
Assert .notNull (id , "Id must not be null!" );
260
221
261
- return this .databaseClient .delete () //
262
- .from (this .entity .getJavaType ()) //
263
- .table (this .entity .getTableName ()) //
264
- .matching (Criteria .where (getIdProperty ().getName ()).is (id )) //
265
- .fetch () //
266
- .rowsUpdated () //
267
- .then ();
222
+ return this .entityOperations .delete (getIdQuery (id ), this .entity .getJavaType ()).then ();
268
223
}
269
224
270
225
/* (non-Javadoc)
@@ -275,20 +230,16 @@ public Mono<Void> deleteById(ID id) {
275
230
public Mono <Void > deleteById (Publisher <ID > idPublisher ) {
276
231
277
232
Assert .notNull (idPublisher , "The Id Publisher must not be null!" );
278
- StatementMapper statementMapper = this .accessStrategy .getStatementMapper ().forType (this .entity .getJavaType ());
279
233
280
234
return Flux .from (idPublisher ).buffer ().filter (ids -> !ids .isEmpty ()).concatMap (ids -> {
281
235
282
236
if (ids .isEmpty ()) {
283
237
return Flux .empty ();
284
238
}
285
239
286
- return this .databaseClient .delete () //
287
- .from (this .entity .getJavaType ()) //
288
- .table (this .entity .getTableName ()) //
289
- .matching (Criteria .where (getIdProperty ().getName ()).in (ids )) //
290
- .fetch () //
291
- .rowsUpdated ();
240
+ String idProperty = getIdProperty ().getName ();
241
+
242
+ return this .entityOperations .delete (Query .query (Criteria .where (idProperty ).in (ids )), this .entity .getJavaType ());
292
243
}).then ();
293
244
}
294
245
@@ -337,14 +288,14 @@ public Mono<Void> deleteAll(Publisher<? extends T> objectPublisher) {
337
288
@ Override
338
289
@ Transactional
339
290
public Mono <Void > deleteAll () {
340
- return this .databaseClient .delete (). from ( this .entity .getTableName ()).then ();
291
+ return this .entityOperations .delete (Query . empty (), this .entity .getJavaType ()).then ();
341
292
}
342
293
343
294
private RelationalPersistentProperty getIdProperty () {
295
+ return this .idProperty .get ();
296
+ }
344
297
345
- return this .converter //
346
- .getMappingContext () //
347
- .getRequiredPersistentEntity (this .entity .getJavaType ()) //
348
- .getRequiredIdProperty ();
298
+ private Query getIdQuery (Object id ) {
299
+ return Query .query (Criteria .where (getIdProperty ().getName ()).is (id ));
349
300
}
350
301
}
0 commit comments