@@ -254,7 +254,7 @@ private <T> Mono<T> saveImpl(T instance) {
254
254
}));
255
255
256
256
if (!entityMetaData .isUsingInternalIds ()) {
257
- return idMono .then (processRelations (entityMetaData , entity , isNewEntity ))
257
+ return idMono .then (processRelations (entityMetaData , entity , isNewEntity , instance ))
258
258
.thenReturn (entity );
259
259
} else {
260
260
return idMono .map (internalId -> {
@@ -263,7 +263,7 @@ private <T> Mono<T> saveImpl(T instance) {
263
263
264
264
return propertyAccessor .getBean ();
265
265
}).flatMap (
266
- savedEntity -> processRelations (entityMetaData , savedEntity , isNewEntity )
266
+ savedEntity -> processRelations (entityMetaData , savedEntity , isNewEntity , instance )
267
267
.thenReturn (savedEntity ));
268
268
}
269
269
}));
@@ -295,9 +295,9 @@ private <T> Mono<Tuple2<T, DynamicLabels>> determineDynamicLabels(T entityToBeSa
295
295
@ Override
296
296
public <T > Flux <T > saveAll (Iterable <T > instances ) {
297
297
298
- Collection <T > entities ;
298
+ List <T > entities ;
299
299
if (instances instanceof Collection ) {
300
- entities = ( Collection <T >) instances ;
300
+ entities = new ArrayList <>(( Collection <T >) instances ) ;
301
301
} else {
302
302
entities = new ArrayList <>();
303
303
instances .forEach (entities ::add );
@@ -341,7 +341,8 @@ public <T> Flux<T> saveAll(Iterable<T> instances) {
341
341
.flatMap (t -> {
342
342
T entityToBeSaved = t .getT2 ();
343
343
boolean isNew = isNewIndicator .get (Math .toIntExact (t .getT1 ()));
344
- return processRelations (entityMetaData , entityToBeSaved , isNew )
344
+ return processRelations (entityMetaData , entityToBeSaved , isNew ,
345
+ entities .get (Math .toIntExact (t .getT1 ())))
345
346
.then (Mono .just (entityToBeSaved ));
346
347
}
347
348
);
@@ -563,10 +564,10 @@ Publisher<Tuple2<Collection<Long>, Collection<Long>>>> iterateAndMapNextLevel(
563
564
}
564
565
565
566
private Mono <Void > processRelations (Neo4jPersistentEntity <?> neo4jPersistentEntity , Object parentObject ,
566
- boolean isParentObjectNew ) {
567
+ boolean isParentObjectNew , Object parentEntity ) {
567
568
568
569
return processNestedRelations (neo4jPersistentEntity , parentObject , isParentObjectNew ,
569
- new NestedRelationshipProcessingStateMachine ());
570
+ new NestedRelationshipProcessingStateMachine (parentEntity ));
570
571
}
571
572
572
573
private Mono <Void > processNestedRelations (Neo4jPersistentEntity <?> sourceEntity , Object parentObject ,
@@ -599,7 +600,7 @@ private Mono<Void> processNestedRelations(Neo4jPersistentEntity<?> sourceEntity,
599
600
600
601
// break recursive procession and deletion of previously created relationships
601
602
ProcessState processState = stateMachine .getStateOf (relationshipDescriptionObverse , relatedValuesToStore );
602
- if (processState == ProcessState .PROCESSED_ALL_RELATIONSHIPS ) {
603
+ if (processState == ProcessState .PROCESSED_ALL_RELATIONSHIPS || processState == ProcessState . PROCESSED_BOTH ) {
603
604
return ;
604
605
}
605
606
@@ -649,9 +650,16 @@ private Mono<Void> processNestedRelations(Neo4jPersistentEntity<?> sourceEntity,
649
650
.flatMap (relatedNode -> {
650
651
Neo4jPersistentEntity <?> targetEntity = neo4jMappingContext
651
652
.getPersistentEntity (relatedNodePreEvt .getClass ());
652
- return Mono .just (targetEntity .isNew (relatedNode )).flatMap (isNew ->
653
- saveRelatedNode (relatedNode , relationshipContext .getAssociationTargetType (),
654
- targetEntity ).flatMap (relatedInternalId -> {
653
+ return Mono .just (targetEntity .isNew (relatedNode )).flatMap (isNew -> {
654
+ Mono <Long > relatedIdMono ;
655
+
656
+ if (processState == ProcessState .PROCESSED_ALL_VALUES ) {
657
+ relatedIdMono = queryRelatedNode (relatedNode , targetEntity );
658
+ } else {
659
+ relatedIdMono = saveRelatedNode (relatedNode , relationshipContext .getAssociationTargetType (),
660
+ targetEntity );
661
+ }
662
+ return relatedIdMono .flatMap (relatedInternalId -> {
655
663
656
664
// if an internal id is used this must get set to link this entity in the next iteration
657
665
PersistentPropertyAccessor <?> targetPropertyAccessor = targetEntity
@@ -688,7 +696,8 @@ private Mono<Void> processNestedRelations(Neo4jPersistentEntity<?> sourceEntity,
688
696
} else {
689
697
return relationshipCreationMonoNested .checkpoint ().then ();
690
698
}
691
- }).checkpoint ());
699
+ }).checkpoint ();
700
+ });
692
701
});
693
702
relationshipCreationMonos .add (createRelationship );
694
703
}
@@ -698,8 +707,23 @@ private Mono<Void> processNestedRelations(Neo4jPersistentEntity<?> sourceEntity,
698
707
});
699
708
}
700
709
701
- private <Y > Mono <Long > saveRelatedNode (Object relatedNode , Class <Y > entityType ,
702
- NodeDescription targetNodeDescription ) {
710
+ private <Y > Mono <Long > queryRelatedNode (Object entity , Neo4jPersistentEntity <?> targetNodeDescription ) {
711
+
712
+ Neo4jPersistentProperty requiredIdProperty = targetNodeDescription .getRequiredIdProperty ();
713
+ PersistentPropertyAccessor <Object > targetPropertyAccessor = targetNodeDescription .getPropertyAccessor (entity );
714
+ Object idValue = targetPropertyAccessor .getProperty (requiredIdProperty );
715
+
716
+ return neo4jClient .query (() ->
717
+ renderer .render (cypherGenerator .prepareMatchOf (targetNodeDescription ,
718
+ targetNodeDescription .getIdExpression ().isEqualTo (parameter (Constants .NAME_OF_ID )))
719
+ .returning (Constants .NAME_OF_INTERNAL_ID )
720
+ .build ())
721
+ )
722
+ .bindAll (Collections .singletonMap (Constants .NAME_OF_ID , idValue ))
723
+ .fetchAs (Long .class ).one ();
724
+ }
725
+
726
+ private <Y > Mono <Long > saveRelatedNode (Object relatedNode , Class <Y > entityType , NodeDescription targetNodeDescription ) {
703
727
704
728
return determineDynamicLabels ((Y ) relatedNode , (Neo4jPersistentEntity <?>) targetNodeDescription )
705
729
.flatMap (t -> {
0 commit comments