diff --git a/src/main/java/org/springframework/data/jpa/repository/support/EntityGraphFactory.java b/src/main/java/org/springframework/data/jpa/repository/support/EntityGraphFactory.java index dc19037b7..1b38b05c9 100644 --- a/src/main/java/org/springframework/data/jpa/repository/support/EntityGraphFactory.java +++ b/src/main/java/org/springframework/data/jpa/repository/support/EntityGraphFactory.java @@ -15,6 +15,8 @@ */ package org.springframework.data.jpa.repository.support; +import java.util.HashMap; +import java.util.Map; import java.util.Set; import javax.persistence.EntityGraph; @@ -27,6 +29,7 @@ import org.springframework.data.mapping.PropertyPath; * Factory class to create an {@link EntityGraph} from a collection of property paths. * * @author Jens Schauder + * @author Petr Strnad * @since 2.6 */ abstract class EntityGraphFactory { @@ -42,16 +45,22 @@ abstract class EntityGraphFactory { public static EntityGraph create(EntityManager entityManager, Class domainType, Set properties) { EntityGraph entityGraph = entityManager.createEntityGraph(domainType); + Map> existingSubgraphs = new HashMap<>(); for (String property : properties) { Subgraph current = null; + String currentFullPath = ""; for (PropertyPath path : PropertyPath.from(property, domainType)) { + currentFullPath += path.getSegment() + "."; + if (path.hasNext()) { - current = current == null ? entityGraph.addSubgraph(path.getSegment()) - : current.addSubgraph(path.getSegment()); + final Subgraph finalCurrent = current; + current = current == null + ? existingSubgraphs.computeIfAbsent(currentFullPath, k -> entityGraph.addSubgraph(path.getSegment())) + : existingSubgraphs.computeIfAbsent(currentFullPath, k -> finalCurrent.addSubgraph(path.getSegment())); continue; } diff --git a/src/test/java/org/springframework/data/jpa/repository/support/EntityGraphFactoryUnitTests.java b/src/test/java/org/springframework/data/jpa/repository/support/EntityGraphFactoryUnitTests.java index 0f225a520..347e06a55 100644 --- a/src/test/java/org/springframework/data/jpa/repository/support/EntityGraphFactoryUnitTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/support/EntityGraphFactoryUnitTests.java @@ -15,8 +15,11 @@ */ package org.springframework.data.jpa.repository.support; -import static java.util.Arrays.*; -import static org.mockito.Mockito.*; +import static java.util.Arrays.asList; +import static org.mockito.Mockito.RETURNS_DEEP_STUBS; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import java.util.HashSet; @@ -31,6 +34,7 @@ import org.junit.jupiter.api.Test; * Unit tests for {@link EntityGraphFactory}. * * @author Jens Schauder + * @author Petr Strnad */ @SuppressWarnings("rawtypes") class EntityGraphFactoryUnitTests { @@ -45,8 +49,7 @@ class EntityGraphFactoryUnitTests { when(em.createEntityGraph(DummyEntity.class)).thenReturn(entityGraph); } - // GH-2329 - @Test + @Test // GH-2329 void simpleSetOfPropertiesGetRegistered() { HashSet properties = new HashSet<>(asList("one", "two")); @@ -57,8 +60,7 @@ class EntityGraphFactoryUnitTests { verify(entityGraph).addAttributeNodes("two"); } - // GH-2329 - @Test + @Test // GH-2329 void setOfCompositePropertiesGetRegisteredPiecewise() { HashSet properties = new HashSet<>(asList("one.two", "eins.zwei.drei")); @@ -76,6 +78,19 @@ class EntityGraphFactoryUnitTests { verify(zwei).addAttributeNodes("drei"); } + @Test // GH-2571 + void multipleSubNodesUnderSameParentNodeShouldWork() { + + HashSet properties = new HashSet<>(asList("one.one", "one.two")); + + entityGraph = EntityGraphFactory.create(em, DummyEntity.class, properties); + + verify(entityGraph).addSubgraph("one"); + Subgraph one = entityGraph.addSubgraph("one"); + verify(one).addAttributeNodes("one"); + verify(one).addAttributeNodes("two"); + } + private static class DummyEntity { DummyEntity one; DummyEntity two;