diff --git a/src/main/java/org/springframework/data/neo4j/core/mapping/DefaultNeo4jEntityConverter.java b/src/main/java/org/springframework/data/neo4j/core/mapping/DefaultNeo4jEntityConverter.java index 930fada99..f0289909f 100644 --- a/src/main/java/org/springframework/data/neo4j/core/mapping/DefaultNeo4jEntityConverter.java +++ b/src/main/java/org/springframework/data/neo4j/core/mapping/DefaultNeo4jEntityConverter.java @@ -302,6 +302,7 @@ final class DefaultNeo4jEntityConverter implements Neo4jEntityConverter { return map(queryResult, nodeDescription, nodeDescription, null, null, relationshipsFromResult, nodesFromResult); } + @SuppressWarnings("unchecked") private ET map(MapAccessor queryResult, Neo4jPersistentEntity nodeDescription, NodeDescription genericTargetNodeDescription, @Nullable Object lastMappedEntity, @Nullable RelationshipDescription relationshipDescription, Collection relationshipsFromResult, Collection nodesFromResult) { @@ -324,7 +325,7 @@ final class DefaultNeo4jEntityConverter implements Neo4jEntityConverter { knownObjects.removeFromInCreation(internalId); - populateProperties(queryResult, nodeDescription, internalId, instance, lastMappedEntity, relationshipsFromResult, nodesFromResult, false); + populateProperties(queryResult, (Neo4jPersistentEntity) genericTargetNodeDescription, nodeDescription, internalId, instance, lastMappedEntity, relationshipsFromResult, nodesFromResult, false); PersistentPropertyAccessor propertyAccessor = concreteNodeDescription.getPropertyAccessor(instance); ET bean = propertyAccessor.getBean(); @@ -349,19 +350,19 @@ final class DefaultNeo4jEntityConverter implements Neo4jEntityConverter { // AND (!!!) // 2. mutable target types // because we cannot just create new instances - populateProperties(queryResult, nodeDescription, internalId, mappedObject, lastMappedEntity, relationshipsFromResult, nodesFromResult, true); + populateProperties(queryResult, (Neo4jPersistentEntity) genericTargetNodeDescription, nodeDescription, internalId, mappedObject, lastMappedEntity, relationshipsFromResult, nodesFromResult, true); } return mappedObject; } - private void populateProperties(MapAccessor queryResult, Neo4jPersistentEntity nodeDescription, String internalId, + private void populateProperties(MapAccessor queryResult, Neo4jPersistentEntity baseNodeDescription, Neo4jPersistentEntity moreConcreteNodeDescription, String internalId, ET mappedObject, @Nullable Object lastMappedEntity, Collection relationshipsFromResult, Collection nodesFromResult, boolean objectAlreadyMapped) { - List allLabels = getLabels(queryResult, nodeDescription); + List allLabels = getLabels(queryResult, moreConcreteNodeDescription); NodeDescriptionAndLabels nodeDescriptionAndLabels = nodeDescriptionStore - .deriveConcreteNodeDescription(nodeDescription, allLabels); + .deriveConcreteNodeDescription(moreConcreteNodeDescription, allLabels); @SuppressWarnings("unchecked") Neo4jPersistentEntity concreteNodeDescription = (Neo4jPersistentEntity) nodeDescriptionAndLabels @@ -389,7 +390,7 @@ final class DefaultNeo4jEntityConverter implements Neo4jEntityConverter { knownObjects.storeObject(internalId, mappedObject); AssociationHandlerSupport.of(concreteNodeDescription).doWithAssociations( - populateFrom(queryResult, nodeDescription, propertyAccessor, isConstructorParameter, objectAlreadyMapped, relationshipsFromResult, nodesFromResult)); + populateFrom(queryResult, baseNodeDescription, propertyAccessor, isConstructorParameter, objectAlreadyMapped, relationshipsFromResult, nodesFromResult)); } @Nullable @@ -488,12 +489,12 @@ final class DefaultNeo4jEntityConverter implements Neo4jEntityConverter { // If we cannot find any value it does not mean that there isn't any. // The result set might contain associations not named CONCRETE_TYPE_TARGET but ABSTRACT_TYPE_TARGET. // For this we bubble up the hierarchy of NodeDescriptions. - result = createInstanceOfRelationships(matchingProperty, values, relationshipDescription, nodeDescription, genericNodeDescription, relationshipsFromResult, nodesFromResult) + result = createInstanceOfRelationships(matchingProperty, values, relationshipDescription, genericNodeDescription, relationshipsFromResult, nodesFromResult) .orElseGet(() -> { NodeDescription parentNodeDescription = nodeDescription.getParentNodeDescription(); T resultValue = null; while (parentNodeDescription != null) { - Optional value = createInstanceOfRelationships(matchingProperty, values, relationshipDescription, parentNodeDescription, parentNodeDescription, relationshipsFromResult, nodesFromResult); + Optional value = createInstanceOfRelationships(matchingProperty, values, relationshipDescription, parentNodeDescription, relationshipsFromResult, nodesFromResult); if (value.isPresent()) { resultValue = (T) value.get(); break; @@ -586,7 +587,7 @@ final class DefaultNeo4jEntityConverter implements Neo4jEntityConverter { && propertyValueNotNull; if (populatedCollection) { - createInstanceOfRelationships(persistentProperty, queryResult, (RelationshipDescription) association, baseDescription, baseDescription, relationshipsFromResult, nodesFromResult, false) + createInstanceOfRelationships(persistentProperty, queryResult, (RelationshipDescription) association, baseDescription, relationshipsFromResult, nodesFromResult, false) .ifPresent(value -> { Collection providedCollection = (Collection) value; Collection existingValue = (Collection) propertyValue; @@ -609,7 +610,7 @@ final class DefaultNeo4jEntityConverter implements Neo4jEntityConverter { return; } - createInstanceOfRelationships(persistentProperty, queryResult, (RelationshipDescription) association, baseDescription, baseDescription, relationshipsFromResult, nodesFromResult) + createInstanceOfRelationships(persistentProperty, queryResult, (RelationshipDescription) association, baseDescription, relationshipsFromResult, nodesFromResult) .ifPresent(value -> propertyAccessor.setProperty(persistentProperty, value)); }; } @@ -633,13 +634,13 @@ final class DefaultNeo4jEntityConverter implements Neo4jEntityConverter { } private Optional createInstanceOfRelationships(Neo4jPersistentProperty persistentProperty, MapAccessor values, - RelationshipDescription relationshipDescription, NodeDescription baseDescription, NodeDescription genericNodeDescription, Collection relationshipsFromResult, + RelationshipDescription relationshipDescription, NodeDescription baseDescription, Collection relationshipsFromResult, Collection nodesFromResult) { - return createInstanceOfRelationships(persistentProperty, values, relationshipDescription, baseDescription, genericNodeDescription, relationshipsFromResult, nodesFromResult, true); + return createInstanceOfRelationships(persistentProperty, values, relationshipDescription, baseDescription, relationshipsFromResult, nodesFromResult, true); } private Optional createInstanceOfRelationships(Neo4jPersistentProperty persistentProperty, MapAccessor values, - RelationshipDescription relationshipDescription, NodeDescription baseDescription, NodeDescription genericNodeDescription, Collection relationshipsFromResult, + RelationshipDescription relationshipDescription, NodeDescription baseDescription, Collection relationshipsFromResult, Collection nodesFromResult, boolean fetchMore) { String typeOfRelationship = relationshipDescription.getType(); @@ -673,8 +674,7 @@ final class DefaultNeo4jEntityConverter implements Neo4jEntityConverter { mappedObjectHandler = (type, mappedObject) -> value.add(mappedObject); } - String collectionName = relationshipDescription.generateRelatedNodesCollectionName(genericNodeDescription); - + String collectionName = relationshipDescription.generateRelatedNodesCollectionName(baseDescription); Value list = values.get(collectionName); List relationshipsAndProperties = new ArrayList<>(); @@ -720,12 +720,12 @@ final class DefaultNeo4jEntityConverter implements Neo4jEntityConverter { if (fetchMore) { mappedObject = sourceNodeId != null && sourceNodeId.equals(targetNodeId) ? knownObjects.getObject("N" + sourceNodeId) - : map(possibleValueNode, concreteTargetNodeDescription, genericNodeDescription, null, null, relationshipsFromResult, nodesFromResult); + : map(possibleValueNode, concreteTargetNodeDescription, baseDescription, null, null, relationshipsFromResult, nodesFromResult); } else { Object objectFromStore = knownObjects.getObject("N" + targetNodeId); mappedObject = objectFromStore != null ? objectFromStore - : map(possibleValueNode, concreteTargetNodeDescription, genericNodeDescription, null, null, relationshipsFromResult, nodesFromResult); + : map(possibleValueNode, concreteTargetNodeDescription, baseDescription, null, null, relationshipsFromResult, nodesFromResult); } if (relationshipDescription.hasRelationshipProperties()) { @@ -757,16 +757,16 @@ final class DefaultNeo4jEntityConverter implements Neo4jEntityConverter { Object valueEntry; if (fetchMore) { - valueEntry = map(relatedEntity, concreteTargetNodeDescription, genericNodeDescription, null, null, relationshipsFromResult, nodesFromResult); + valueEntry = map(relatedEntity, concreteTargetNodeDescription, genericTargetNodeDescription, null, null, relationshipsFromResult, nodesFromResult); } else { Object objectFromStore = knownObjects.getObject(getInternalId(relatedEntity, null)); valueEntry = objectFromStore != null ? objectFromStore - : map(relatedEntity, concreteTargetNodeDescription, genericNodeDescription, null, null, relationshipsFromResult, nodesFromResult); + : map(relatedEntity, concreteTargetNodeDescription, genericTargetNodeDescription, null, null, relationshipsFromResult, nodesFromResult); } if (relationshipDescription.hasRelationshipProperties()) { - String sourceLabel = relationshipDescription.getSource().getMostAbstractParentLabel(genericNodeDescription); + String sourceLabel = relationshipDescription.getSource().getMostAbstractParentLabel(baseDescription); String relationshipSymbolicName = sourceLabel + RelationshipDescription.NAME_OF_RELATIONSHIP + targetLabel; Relationship relatedEntityRelationship = relatedEntity.get(relationshipSymbolicName)