@@ -662,86 +662,89 @@ private Optional<Object> createInstanceOfRelationships(Neo4jPersistentProperty p
662
662
663
663
String elementId = IdentitySupport .getElementId (values );
664
664
Long internalId = IdentitySupport .getInternalId (values );
665
- boolean hasGeneratedIdValue = elementId != null || internalId != null ;
665
+ boolean hasIdValue = elementId != null || internalId != null ;
666
666
667
- if (relationshipListEmptyOrNull && hasGeneratedIdValue ) {
667
+ if (relationshipListEmptyOrNull && hasIdValue ) {
668
668
String sourceNodeId ;
669
669
Function <Relationship , String > sourceIdSelector ;
670
670
Function <Relationship , String > targetIdSelector = relationshipDescription .isIncoming () ? Relationship ::startNodeElementId : Relationship ::endNodeElementId ;
671
671
672
- if (internalId != null ) {
672
+ if (elementId != null ) {
673
+ sourceNodeId = elementId ;
674
+ sourceIdSelector = relationshipDescription .isIncoming () ? Relationship ::endNodeElementId : Relationship ::startNodeElementId ;
675
+ } else {
673
676
// this can happen when someone used dto mapping and added the "classical" approach
674
677
sourceNodeId = Long .toString (internalId );
675
678
Function <Relationship , Long > hlp = relationshipDescription .isIncoming () ? Relationship ::endNodeId : Relationship ::startNodeId ;
676
679
sourceIdSelector = hlp .andThen (l -> Long .toString (l ));
677
- } else {
678
- sourceNodeId = elementId ;
679
- sourceIdSelector = relationshipDescription .isIncoming () ? Relationship ::endNodeElementId : Relationship ::startNodeElementId ;
680
680
}
681
681
682
682
// Retrieve all matching relationships from the result's list(s)
683
683
Collection <Relationship > allMatchingTypeRelationshipsInResult =
684
684
extractMatchingRelationships (relationshipsFromResult , relationshipDescription , typeOfRelationship ,
685
685
(possibleRelationship ) -> sourceIdSelector .apply (possibleRelationship ).equals (sourceNodeId ));
686
686
687
- // Retrieve all nodes from the result's list(s)
688
- Collection < Node > allNodesWithMatchingLabelInResult = extractMatchingNodes ( nodesFromResult , targetLabel );
687
+ // Fast exit if there is no relationship that can be mapped
688
+ if (! allMatchingTypeRelationshipsInResult . isEmpty ()) {
689
689
690
- for (Node possibleValueNode : allNodesWithMatchingLabelInResult ) {
691
- String targetNodeId = IdentitySupport .getElementId (possibleValueNode );
690
+ // Retrieve all nodes from the result's list(s)
691
+ Collection <Node > allNodesWithMatchingLabelInResult = extractMatchingNodes (nodesFromResult , targetLabel );
692
+ for (Node possibleValueNode : allNodesWithMatchingLabelInResult ) {
693
+ String targetNodeId = IdentitySupport .getElementId (possibleValueNode );
692
694
693
- Neo4jPersistentEntity <?> concreteTargetNodeDescription =
694
- getMostConcreteTargetNodeDescription (genericTargetNodeDescription , possibleValueNode );
695
-
696
- Set <Relationship > relationshipsProcessed = new HashSet <>();
697
- for (Relationship possibleRelationship : allMatchingTypeRelationshipsInResult ) {
698
- if (targetIdSelector .apply (possibleRelationship ).equals (targetNodeId )) {
699
-
700
- // Reduce the amount of relationships in the candidate list.
701
- // If this relationship got processed twice (OUTGOING, INCOMING), it is never needed again
702
- // and therefor should not be in the list.
703
- // Otherwise, for highly linked data it could potentially cause a StackOverflowError.
704
- String direction = relationshipDescription .getDirection ().name ();
705
- if (knownObjects .hasProcessedRelationshipCompletely ("R" + direction + IdentitySupport .getElementId (possibleRelationship ))) {
706
- relationshipsFromResult .remove (possibleRelationship );
707
- }
708
- // If the target is the same(equal) node, get the related object from the cache.
709
- // Avoiding the call to the map method also breaks an endless cycle of trying to finish
710
- // the property population of _this_ object.
711
- // The initial population will happen at the end of this mapping. This is sufficient because
712
- // it only affects properties not changing the instance of the object.
713
- Object mappedObject ;
714
- if (fetchMore ) {
715
- mappedObject = sourceNodeId != null && sourceNodeId .equals (targetNodeId )
716
- ? knownObjects .getObject ("N" + sourceNodeId )
717
- : map (possibleValueNode , concreteTargetNodeDescription , baseDescription , null , null , relationshipsFromResult , nodesFromResult );
718
- } else {
719
- Object objectFromStore = knownObjects .getObject ("N" + targetNodeId );
720
- mappedObject = objectFromStore != null
721
- ? objectFromStore
722
- : map (possibleValueNode , concreteTargetNodeDescription , baseDescription , null , null , relationshipsFromResult , nodesFromResult );
723
- }
695
+ Neo4jPersistentEntity <?> concreteTargetNodeDescription =
696
+ getMostConcreteTargetNodeDescription (genericTargetNodeDescription , possibleValueNode );
697
+
698
+ Set <Relationship > relationshipsProcessed = new HashSet <>();
699
+ for (Relationship possibleRelationship : allMatchingTypeRelationshipsInResult ) {
700
+ if (targetIdSelector .apply (possibleRelationship ).equals (targetNodeId )) {
724
701
725
- if (relationshipDescription .hasRelationshipProperties ()) {
726
- Object relationshipProperties ;
727
- Neo4jPersistentEntity <?> relationshipPropertiesEntity = (Neo4jPersistentEntity <?>) relationshipDescription .getRelationshipPropertiesEntity ();
702
+ // Reduce the amount of relationships in the candidate list.
703
+ // If this relationship got processed twice (OUTGOING, INCOMING), it is never needed again
704
+ // and therefor should not be in the list.
705
+ // Otherwise, for highly linked data it could potentially cause a StackOverflowError.
706
+ String direction = relationshipDescription .getDirection ().name ();
707
+ if (knownObjects .hasProcessedRelationshipCompletely ("R" + direction + IdentitySupport .getElementId (possibleRelationship ))) {
708
+ relationshipsFromResult .remove (possibleRelationship );
709
+ }
710
+ // If the target is the same(equal) node, get the related object from the cache.
711
+ // Avoiding the call to the map method also breaks an endless cycle of trying to finish
712
+ // the property population of _this_ object.
713
+ // The initial population will happen at the end of this mapping. This is sufficient because
714
+ // it only affects properties not changing the instance of the object.
715
+ Object mappedObject ;
728
716
if (fetchMore ) {
729
- relationshipProperties = map (possibleRelationship , relationshipPropertiesEntity , relationshipPropertiesEntity , mappedObject , relationshipDescription , relationshipsFromResult , nodesFromResult );
717
+ mappedObject = sourceNodeId != null && sourceNodeId .equals (targetNodeId )
718
+ ? knownObjects .getObject ("N" + sourceNodeId )
719
+ : map (possibleValueNode , concreteTargetNodeDescription , baseDescription , null , null , relationshipsFromResult , nodesFromResult );
720
+ } else {
721
+ Object objectFromStore = knownObjects .getObject ("N" + targetNodeId );
722
+ mappedObject = objectFromStore != null
723
+ ? objectFromStore
724
+ : map (possibleValueNode , concreteTargetNodeDescription , baseDescription , null , null , relationshipsFromResult , nodesFromResult );
725
+ }
726
+
727
+ if (relationshipDescription .hasRelationshipProperties ()) {
728
+ Object relationshipProperties ;
729
+ Neo4jPersistentEntity <?> relationshipPropertiesEntity = (Neo4jPersistentEntity <?>) relationshipDescription .getRelationshipPropertiesEntity ();
730
+ if (fetchMore ) {
731
+ relationshipProperties = map (possibleRelationship , relationshipPropertiesEntity , relationshipPropertiesEntity , mappedObject , relationshipDescription , relationshipsFromResult , nodesFromResult );
732
+ } else {
733
+ Object objectFromStore = knownObjects .getObject (IdentitySupport .getPrefixedElementId (possibleRelationship , relationshipDescription .getDirection ().name ()));
734
+ relationshipProperties = objectFromStore != null
735
+ ? objectFromStore
736
+ : map (possibleRelationship , relationshipPropertiesEntity , relationshipPropertiesEntity , mappedObject , relationshipDescription , relationshipsFromResult , nodesFromResult );
737
+ }
738
+ relationshipsAndProperties .add (relationshipProperties );
739
+ mappedObjectHandler .accept (possibleRelationship .type (), relationshipProperties );
730
740
} else {
731
- Object objectFromStore = knownObjects .getObject (IdentitySupport .getPrefixedElementId (possibleRelationship , relationshipDescription .getDirection ().name ()));
732
- relationshipProperties = objectFromStore != null
733
- ? objectFromStore
734
- : map (possibleRelationship , relationshipPropertiesEntity , relationshipPropertiesEntity , mappedObject , relationshipDescription , relationshipsFromResult , nodesFromResult );
741
+ mappedObjectHandler .accept (possibleRelationship .type (), mappedObject );
735
742
}
736
- relationshipsAndProperties .add (relationshipProperties );
737
- mappedObjectHandler .accept (possibleRelationship .type (), relationshipProperties );
738
- } else {
739
- mappedObjectHandler .accept (possibleRelationship .type (), mappedObject );
743
+ relationshipsProcessed .add (possibleRelationship );
740
744
}
741
- relationshipsProcessed .add (possibleRelationship );
742
745
}
746
+ allMatchingTypeRelationshipsInResult .removeAll (relationshipsProcessed );
743
747
}
744
- allMatchingTypeRelationshipsInResult .removeAll (relationshipsProcessed );
745
748
}
746
749
} else if (!relationshipListEmptyOrNull ) {
747
750
for (Value relatedEntity : list .asList (Function .identity ())) {
0 commit comments