16
16
package org .springframework .data .jdbc .core ;
17
17
18
18
import java .util .ArrayList ;
19
+ import java .util .Iterator ;
19
20
import java .util .List ;
20
21
import java .util .function .Function ;
21
22
import java .util .stream .Collectors ;
31
32
import org .springframework .data .mapping .IdentifierAccessor ;
32
33
import org .springframework .data .mapping .callback .EntityCallbacks ;
33
34
import org .springframework .data .relational .core .conversion .AggregateChange ;
34
- import org .springframework .data .relational .core .conversion .AggregateChangeWithRoot ;
35
+ import org .springframework .data .relational .core .conversion .RootAggregateChange ;
36
+ import org .springframework .data .relational .core .conversion .BatchingAggregateChange ;
35
37
import org .springframework .data .relational .core .conversion .MutableAggregateChange ;
36
38
import org .springframework .data .relational .core .conversion .RelationalEntityDeleteWriter ;
37
39
import org .springframework .data .relational .core .conversion .RelationalEntityInsertWriter ;
44
46
import org .springframework .data .support .PageableExecutionUtils ;
45
47
import org .springframework .lang .Nullable ;
46
48
import org .springframework .util .Assert ;
49
+ import org .springframework .util .ClassUtils ;
47
50
48
51
/**
49
52
* {@link JdbcAggregateOperations} implementation, storing aggregates in and obtaining them from a JDBC data store.
@@ -141,13 +144,15 @@ public <T> T save(T instance) {
141
144
142
145
Assert .notNull (instance , "Aggregate instance must not be null!" );
143
146
144
- RelationalPersistentEntity <?> persistentEntity = context .getRequiredPersistentEntity (instance .getClass ());
147
+ return performSave (instance , changeCreatorSelectorForSave (instance ));
148
+ }
145
149
146
- Function <T , AggregateChangeWithRoot <T >> changeCreator = persistentEntity .isNew (instance )
147
- ? entity -> createInsertChange (prepareVersionForInsert (entity ))
148
- : entity -> createUpdateChange (prepareVersionForUpdate (entity ));
150
+ @ Override
151
+ public <T > Iterable <T > saveAll (Iterable <T > instances ) {
152
+
153
+ Assert .isTrue (instances .iterator ().hasNext (), "Aggregate instances must not be empty!" );
149
154
150
- return store ( instance , changeCreator , persistentEntity );
155
+ return performSaveAll ( instances );
151
156
}
152
157
153
158
/**
@@ -162,9 +167,7 @@ public <T> T insert(T instance) {
162
167
163
168
Assert .notNull (instance , "Aggregate instance must not be null!" );
164
169
165
- RelationalPersistentEntity <?> persistentEntity = context .getRequiredPersistentEntity (instance .getClass ());
166
-
167
- return store (instance , entity -> createInsertChange (prepareVersionForInsert (entity )), persistentEntity );
170
+ return performSave (instance , entity -> createInsertChange (prepareVersionForInsert (entity )));
168
171
}
169
172
170
173
/**
@@ -179,9 +182,7 @@ public <T> T update(T instance) {
179
182
180
183
Assert .notNull (instance , "Aggregate instance must not be null!" );
181
184
182
- RelationalPersistentEntity <?> persistentEntity = context .getRequiredPersistentEntity (instance .getClass ());
183
-
184
- return store (instance , entity -> createUpdateChange (prepareVersionForUpdate (entity )), persistentEntity );
185
+ return performSave (instance , entity -> createUpdateChange (prepareVersionForUpdate (entity )));
185
186
}
186
187
187
188
@ Override
@@ -280,29 +281,33 @@ public void deleteAll(Class<?> domainType) {
280
281
Assert .notNull (domainType , "Domain type must not be null!" );
281
282
282
283
MutableAggregateChange <?> change = createDeletingChange (domainType );
283
- executor .execute (change );
284
+ executor .executeDelete (change );
285
+ }
286
+
287
+ private <T > T afterExecute (AggregateChange <T > change , T entityAfterExecution ) {
288
+
289
+ Object identifier = context .getRequiredPersistentEntity (change .getEntityType ())
290
+ .getIdentifierAccessor (entityAfterExecution ).getIdentifier ();
291
+
292
+ Assert .notNull (identifier , "After saving the identifier must not be null!" );
293
+
294
+ return triggerAfterSave (entityAfterExecution , change );
284
295
}
285
296
286
- private <T > T store (T aggregateRoot , Function < T , AggregateChangeWithRoot < T >> changeCreator ,
287
- RelationalPersistentEntity <?> persistentEntity ) {
297
+ private <T > RootAggregateChange < T > beforeExecute (T aggregateRoot ,
298
+ Function < T , RootAggregateChange < T >> changeCreator ) {
288
299
289
300
Assert .notNull (aggregateRoot , "Aggregate instance must not be null!" );
290
301
291
302
aggregateRoot = triggerBeforeConvert (aggregateRoot );
292
303
293
- AggregateChangeWithRoot <T > change = changeCreator .apply (aggregateRoot );
304
+ RootAggregateChange <T > change = changeCreator .apply (aggregateRoot );
294
305
295
306
aggregateRoot = triggerBeforeSave (change .getRoot (), change );
296
307
297
308
change .setRoot (aggregateRoot );
298
309
299
- T entityAfterExecution = executor .execute (change );
300
-
301
- Object identifier = persistentEntity .getIdentifierAccessor (entityAfterExecution ).getIdentifier ();
302
-
303
- Assert .notNull (identifier , "After saving the identifier must not be null!" );
304
-
305
- return triggerAfterSave (entityAfterExecution , change );
310
+ return change ;
306
311
}
307
312
308
313
private <T > void deleteTree (Object id , @ Nullable T entity , Class <T > domainType ) {
@@ -311,23 +316,70 @@ private <T> void deleteTree(Object id, @Nullable T entity, Class<T> domainType)
311
316
312
317
entity = triggerBeforeDelete (entity , id , change );
313
318
314
- executor .execute (change );
319
+ executor .executeDelete (change );
315
320
316
321
triggerAfterDelete (entity , id , change );
317
322
}
318
323
319
- private <T > AggregateChangeWithRoot <T > createInsertChange (T instance ) {
324
+ private <T > T performSave (T instance , Function <T , RootAggregateChange <T >> changeCreator ) {
325
+
326
+ // noinspection unchecked
327
+ BatchingAggregateChange <T , RootAggregateChange <T >> batchingAggregateChange = //
328
+ BatchingAggregateChange .forSave ((Class <T >) ClassUtils .getUserClass (instance ));
329
+ batchingAggregateChange .add (beforeExecute (instance , changeCreator ));
330
+
331
+ Iterator <T > afterExecutionIterator = executor .executeSave (batchingAggregateChange ).iterator ();
332
+
333
+ Assert .isTrue (afterExecutionIterator .hasNext (), "Instances after execution must not be empty!" );
334
+
335
+ return afterExecute (batchingAggregateChange , afterExecutionIterator .next ());
336
+ }
337
+
338
+ private <T > List <T > performSaveAll (Iterable <T > instances ) {
339
+
340
+ Iterator <T > iterator = instances .iterator ();
341
+ T firstInstance = iterator .next ();
342
+
343
+ // noinspection unchecked
344
+ BatchingAggregateChange <T , RootAggregateChange <T >> batchingAggregateChange = //
345
+ BatchingAggregateChange .forSave ((Class <T >) ClassUtils .getUserClass (firstInstance ));
346
+ batchingAggregateChange .add (beforeExecute (firstInstance , changeCreatorSelectorForSave (firstInstance )));
347
+
348
+ while (iterator .hasNext ()) {
349
+ T instance = iterator .next ();
350
+ batchingAggregateChange .add (beforeExecute (instance , changeCreatorSelectorForSave (instance )));
351
+ }
352
+
353
+ List <T > instancesAfterExecution = executor .executeSave (batchingAggregateChange );
354
+
355
+ ArrayList <T > results = new ArrayList <>(instancesAfterExecution .size ());
356
+ for (T instance : instancesAfterExecution ) {
357
+ results .add (afterExecute (batchingAggregateChange , instance ));
358
+ }
359
+
360
+ return results ;
361
+ }
362
+
363
+ private <T > Function <T , RootAggregateChange <T >> changeCreatorSelectorForSave (T instance ) {
364
+
365
+ return context .getRequiredPersistentEntity (instance .getClass ()).isNew (instance )
366
+ ? entity -> createInsertChange (prepareVersionForInsert (entity ))
367
+ : entity -> createUpdateChange (prepareVersionForUpdate (entity ));
368
+ }
369
+
370
+ private <T > RootAggregateChange <T > createInsertChange (T instance ) {
320
371
321
- AggregateChangeWithRoot <T > aggregateChange = MutableAggregateChange .forSave (instance );
372
+ RootAggregateChange <T > aggregateChange = MutableAggregateChange .forSave (instance );
322
373
new RelationalEntityInsertWriter <T >(context ).write (instance , aggregateChange );
323
374
return aggregateChange ;
324
375
}
325
376
326
- private <T > AggregateChangeWithRoot <T > createUpdateChange (EntityAndPreviousVersion <T > entityAndVersion ) {
377
+ private <T > RootAggregateChange <T > createUpdateChange (EntityAndPreviousVersion <T > entityAndVersion ) {
327
378
328
- AggregateChangeWithRoot <T > aggregateChange = MutableAggregateChange .forSave (entityAndVersion .entity ,
379
+ RootAggregateChange <T > aggregateChange = MutableAggregateChange .forSave (entityAndVersion .entity ,
329
380
entityAndVersion .version );
330
- new RelationalEntityUpdateWriter <T >(context ).write (entityAndVersion .entity , aggregateChange );
381
+ new RelationalEntityUpdateWriter <T >(context ).write (entityAndVersion .entity ,
382
+ aggregateChange );
331
383
return aggregateChange ;
332
384
}
333
385
0 commit comments