1717
1818import java .util .*;
1919import java .util .function .BiConsumer ;
20+ import java .util .function .Function ;
2021import java .util .stream .Collectors ;
2122
2223import org .springframework .dao .IncorrectUpdateSemanticsDataAccessException ;
@@ -72,19 +73,16 @@ class JdbcAggregateChangeExecutionContext {
7273
7374 <T > void executeInsertRoot (DbAction .InsertRoot <T > insert ) {
7475
75- Object id = accessStrategy .insert (insert .getEntity (), insert .getEntityType (), Identifier .empty (),
76- insert .getIdValueSource ());
76+ Object id = accessStrategy .insert (insert .getEntity (), insert .getEntityType (), Identifier .empty (), insert .getIdValueSource ());
7777 add (new DbActionExecutionResult (insert , id ));
7878 }
7979
8080 <T > void executeBatchInsertRoot (DbAction .BatchInsertRoot <T > batchInsertRoot ) {
8181
8282 List <DbAction .InsertRoot <T >> inserts = batchInsertRoot .getActions ();
83- List <InsertSubject <T >> insertSubjects = inserts .stream ()
84- .map (insert -> InsertSubject .describedBy (insert .getEntity (), Identifier .empty ())).collect (Collectors .toList ());
83+ List <InsertSubject <T >> insertSubjects = inserts .stream ().map (insert -> InsertSubject .describedBy (insert .getEntity (), Identifier .empty ())).collect (Collectors .toList ());
8584
86- Object [] ids = accessStrategy .insert (insertSubjects , batchInsertRoot .getEntityType (),
87- batchInsertRoot .getBatchValue ());
85+ Object [] ids = accessStrategy .insert (insertSubjects , batchInsertRoot .getEntityType (), batchInsertRoot .getBatchValue ());
8886
8987 for (int i = 0 ; i < inserts .size (); i ++) {
9088 add (new DbActionExecutionResult (inserts .get (i ), ids .length > 0 ? ids [i ] : null ));
@@ -94,17 +92,14 @@ <T> void executeBatchInsertRoot(DbAction.BatchInsertRoot<T> batchInsertRoot) {
9492 <T > void executeInsert (DbAction .Insert <T > insert ) {
9593
9694 Identifier parentKeys = getParentKeys (insert , converter );
97- Object id = accessStrategy .insert (insert .getEntity (), insert .getEntityType (), parentKeys ,
98- insert .getIdValueSource ());
95+ Object id = accessStrategy .insert (insert .getEntity (), insert .getEntityType (), parentKeys , insert .getIdValueSource ());
9996 add (new DbActionExecutionResult (insert , id ));
10097 }
10198
10299 <T > void executeBatchInsert (DbAction .BatchInsert <T > batchInsert ) {
103100
104101 List <DbAction .Insert <T >> inserts = batchInsert .getActions ();
105- List <InsertSubject <T >> insertSubjects = inserts .stream ()
106- .map (insert -> InsertSubject .describedBy (insert .getEntity (), getParentKeys (insert , converter )))
107- .collect (Collectors .toList ());
102+ List <InsertSubject <T >> insertSubjects = inserts .stream ().map (insert -> InsertSubject .describedBy (insert .getEntity (), getParentKeys (insert , converter ))).collect (Collectors .toList ());
108103
109104 Object [] ids = accessStrategy .insert (insertSubjects , batchInsert .getEntityType (), batchInsert .getBatchValue ());
110105
@@ -176,20 +171,34 @@ private Identifier getParentKeys(DbAction.WithDependingOn<?> action, JdbcConvert
176171 Object id = getParentId (action );
177172
178173 JdbcIdentifierBuilder identifier = JdbcIdentifierBuilder //
179- .forBackReferences (converter , context .getAggregatePath (action .getPropertyPath ()), id );
174+ .forBackReferences (converter , context .getAggregatePath (action .getPropertyPath ()),
175+ getValueProvider (id , context .getAggregatePath (action .getPropertyPath ()), converter ));
180176
181- for (Map .Entry <PersistentPropertyPath <RelationalPersistentProperty >, Object > qualifier : action .getQualifiers ()
182- .entrySet ()) {
177+ for (Map .Entry <PersistentPropertyPath <RelationalPersistentProperty >, Object > qualifier : action .getQualifiers ().entrySet ()) {
183178 identifier = identifier .withQualifier (context .getAggregatePath (qualifier .getKey ()), qualifier .getValue ());
184179 }
185180
186181 return identifier .build ();
187182 }
188183
184+ static Function <AggregatePath , Object > getValueProvider (Object idValue , AggregatePath path , JdbcConverter converter ) {
185+
186+ RelationalPersistentEntity <?> entity = converter .getMappingContext ().getPersistentEntity (path .getIdDefiningParentPath ().getRequiredIdProperty ().getType ());
187+
188+ Function <AggregatePath , Object > valueProvider = ap -> {
189+ if (entity == null ) {
190+ return idValue ;
191+ } else {
192+ PersistentPropertyPathAccessor <Object > propertyPathAccessor = entity .getPropertyPathAccessor (idValue );
193+ return propertyPathAccessor .getProperty (ap .getRequiredPersistentPropertyPath ());
194+ }
195+ };
196+ return valueProvider ;
197+ }
198+
189199 private Object getParentId (DbAction .WithDependingOn <?> action ) {
190200
191- DbAction .WithEntity <?> idOwningAction = getIdOwningAction (action ,
192- context .getAggregatePath (action .getPropertyPath ()).getIdDefiningParentPath ());
201+ DbAction .WithEntity <?> idOwningAction = getIdOwningAction (action , context .getAggregatePath (action .getPropertyPath ()).getIdDefiningParentPath ());
193202
194203 return getPotentialGeneratedIdFrom (idOwningAction );
195204 }
@@ -198,8 +207,7 @@ private DbAction.WithEntity<?> getIdOwningAction(DbAction.WithEntity<?> action,
198207
199208 if (!(action instanceof DbAction .WithDependingOn <?> withDependingOn )) {
200209
201- Assert .state (idPath .isRoot (),
202- "When the id path is not empty the id providing action should be of type WithDependingOn" );
210+ Assert .state (idPath .isRoot (), "When the id path is not empty the id providing action should be of type WithDependingOn" );
203211
204212 return action ;
205213 }
@@ -267,20 +275,16 @@ <T> List<T> populateIdsIfNecessary() {
267275
268276 if (newEntity != action .getEntity ()) {
269277
270- cascadingValues .stage (insert .getDependingOn (), insert .getPropertyPath (),
271- qualifierValue , newEntity );
278+ cascadingValues .stage (insert .getDependingOn (), insert .getPropertyPath (), qualifierValue , newEntity );
272279 } else if (insert .getPropertyPath ().getLeafProperty ().isCollectionLike ()) {
273280
274- cascadingValues .gather (insert .getDependingOn (), insert .getPropertyPath (),
275- qualifierValue , newEntity );
281+ cascadingValues .gather (insert .getDependingOn (), insert .getPropertyPath (), qualifierValue , newEntity );
276282 }
277283 }
278284 }
279285
280286 if (roots .isEmpty ()) {
281- throw new IllegalStateException (
282- String .format ("Cannot retrieve the resulting instance(s) unless a %s or %s action was successfully executed" ,
283- DbAction .InsertRoot .class .getName (), DbAction .UpdateRoot .class .getName ()));
287+ throw new IllegalStateException (String .format ("Cannot retrieve the resulting instance(s) unless a %s or %s action was successfully executed" , DbAction .InsertRoot .class .getName (), DbAction .UpdateRoot .class .getName ()));
284288 }
285289
286290 Collections .reverse (roots );
@@ -289,23 +293,19 @@ <T> List<T> populateIdsIfNecessary() {
289293 }
290294
291295 @ SuppressWarnings ("unchecked" )
292- private <S > Object setIdAndCascadingProperties (DbAction .WithEntity <S > action , @ Nullable Object generatedId ,
293- StagedValues cascadingValues ) {
296+ private <S > Object setIdAndCascadingProperties (DbAction .WithEntity <S > action , @ Nullable Object generatedId , StagedValues cascadingValues ) {
294297
295298 S originalEntity = action .getEntity ();
296299
297- RelationalPersistentEntity <S > persistentEntity = (RelationalPersistentEntity <S >) context
298- .getRequiredPersistentEntity (action .getEntityType ());
299- PersistentPropertyPathAccessor <S > propertyAccessor = converter .getPropertyAccessor (persistentEntity ,
300- originalEntity );
300+ RelationalPersistentEntity <S > persistentEntity = (RelationalPersistentEntity <S >) context .getRequiredPersistentEntity (action .getEntityType ());
301+ PersistentPropertyPathAccessor <S > propertyAccessor = converter .getPropertyAccessor (persistentEntity , originalEntity );
301302
302303 if (IdValueSource .GENERATED .equals (action .getIdValueSource ())) {
303304 propertyAccessor .setProperty (persistentEntity .getRequiredIdProperty (), generatedId );
304305 }
305306
306307 // set values of changed immutables referenced by this entity
307- cascadingValues .forEachPath (action , (persistentPropertyPath , o ) -> propertyAccessor
308- .setProperty (getRelativePath (action , persistentPropertyPath ), o ));
308+ cascadingValues .forEachPath (action , (persistentPropertyPath , o ) -> propertyAccessor .setProperty (getRelativePath (action , persistentPropertyPath ), o ));
309309
310310 return propertyAccessor .getBean ();
311311 }
@@ -337,8 +337,7 @@ private <T> void updateWithoutVersion(DbAction.UpdateRoot<T> update) {
337337
338338 if (!accessStrategy .update (update .getEntity (), update .getEntityType ())) {
339339
340- throw new IncorrectUpdateSemanticsDataAccessException (
341- String .format (UPDATE_FAILED , update .getEntity (), getIdFrom (update )));
340+ throw new IncorrectUpdateSemanticsDataAccessException (String .format (UPDATE_FAILED , update .getEntity (), getIdFrom (update )));
342341 }
343342 }
344343
@@ -359,21 +358,20 @@ private <T> void updateWithVersion(DbAction.UpdateRoot<T> update) {
359358 */
360359 private static class StagedValues {
361360
362- static final List <MultiValueAggregator <?>> aggregators = Arrays .asList (SetAggregator .INSTANCE , MapAggregator .INSTANCE ,
363- ListAggregator .INSTANCE , SingleElementAggregator .INSTANCE );
361+ static final List <MultiValueAggregator <?>> aggregators = Arrays .asList (SetAggregator .INSTANCE , MapAggregator .INSTANCE , ListAggregator .INSTANCE , SingleElementAggregator .INSTANCE );
364362
365363 Map <DbAction , Map <PersistentPropertyPath , StagedValue >> values = new HashMap <>();
366364
367365 /**
368366 * Adds a value that needs to be set in an entity higher up in the tree of entities in the aggregate. If the
369367 * attribute to be set is multivalued this method expects only a single element.
370368 *
371- * @param action The action responsible for persisting the entity that needs the added value set. Must not be
372- * {@literal null}.
373- * @param path The path to the property in which to set the value. Must not be {@literal null}.
369+ * @param action The action responsible for persisting the entity that needs the added value set. Must not be
370+ * {@literal null}.
371+ * @param path The path to the property in which to set the value. Must not be {@literal null}.
374372 * @param qualifier If {@code path} is a qualified multivalued properties this parameter contains the qualifier. May
375- * be {@literal null}.
376- * @param value The value to be set. Must not be {@literal null}.
373+ * be {@literal null}.
374+ * @param value The value to be set. Must not be {@literal null}.
377375 */
378376 void stage (DbAction <?> action , PersistentPropertyPath path , @ Nullable Object qualifier , Object value ) {
379377
@@ -386,11 +384,9 @@ <T> StagedValue gather(DbAction<?> action, PersistentPropertyPath path, @Nullabl
386384
387385 MultiValueAggregator <T > aggregator = getAggregatorFor (path );
388386
389- Map <PersistentPropertyPath , StagedValue > valuesForPath = this .values .computeIfAbsent (action ,
390- dbAction -> new HashMap <>());
387+ Map <PersistentPropertyPath , StagedValue > valuesForPath = this .values .computeIfAbsent (action , dbAction -> new HashMap <>());
391388
392- StagedValue stagedValue = valuesForPath .computeIfAbsent (path ,
393- persistentPropertyPath -> new StagedValue (aggregator .createEmptyInstance ()));
389+ StagedValue stagedValue = valuesForPath .computeIfAbsent (path , persistentPropertyPath -> new StagedValue (aggregator .createEmptyInstance ()));
394390 T currentValue = (T ) stagedValue .value ;
395391
396392 stagedValue .value = aggregator .add (currentValue , qualifier , value );
@@ -430,7 +426,8 @@ void forEachPath(DbAction<?> dbAction, BiConsumer<PersistentPropertyPath, Object
430426 }
431427
432428 private static class StagedValue {
433- @ Nullable Object value ;
429+ @ Nullable
430+ Object value ;
434431 boolean isStaged ;
435432
436433 public StagedValue (@ Nullable Object value ) {
0 commit comments