Skip to content

Commit e737efd

Browse files
pstrnadgregturn
authored andcommitted
Fix EntityGraphFactory to not overwrite prior subgraphs.
Resolves #2527.
1 parent 1604a22 commit e737efd

File tree

2 files changed

+36
-12
lines changed

2 files changed

+36
-12
lines changed

spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/support/EntityGraphFactory.java

+13-4
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,21 @@
1515
*/
1616
package org.springframework.data.jpa.repository.support;
1717

18-
import java.util.Set;
19-
2018
import jakarta.persistence.EntityGraph;
2119
import jakarta.persistence.EntityManager;
2220
import jakarta.persistence.Subgraph;
2321

22+
import java.util.HashMap;
23+
import java.util.Map;
24+
import java.util.Set;
25+
2426
import org.springframework.data.mapping.PropertyPath;
2527

2628
/**
2729
* Factory class to create an {@link EntityGraph} from a collection of property paths.
2830
*
2931
* @author Jens Schauder
32+
* @author Petr Strnad
3033
* @since 2.6
3134
*/
3235
abstract class EntityGraphFactory {
@@ -42,16 +45,22 @@ abstract class EntityGraphFactory {
4245
public static <T> EntityGraph<T> create(EntityManager entityManager, Class<T> domainType, Set<String> properties) {
4346

4447
EntityGraph<T> entityGraph = entityManager.createEntityGraph(domainType);
48+
Map<String, Subgraph<Object>> existingSubgraphs = new HashMap<>();
4549

4650
for (String property : properties) {
4751

4852
Subgraph<Object> current = null;
53+
String currentFullPath = "";
4954

5055
for (PropertyPath path : PropertyPath.from(property, domainType)) {
5156

57+
currentFullPath += path.getSegment() + ".";
58+
5259
if (path.hasNext()) {
53-
current = current == null ? entityGraph.addSubgraph(path.getSegment())
54-
: current.addSubgraph(path.getSegment());
60+
final Subgraph<Object> finalCurrent = current;
61+
current = current == null
62+
? existingSubgraphs.computeIfAbsent(currentFullPath, k -> entityGraph.addSubgraph(path.getSegment()))
63+
: existingSubgraphs.computeIfAbsent(currentFullPath, k -> finalCurrent.addSubgraph(path.getSegment()));
5564
continue;
5665
}
5766

spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/support/EntityGraphFactoryUnitTests.java

+23-8
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,26 @@
1515
*/
1616
package org.springframework.data.jpa.repository.support;
1717

18-
import static java.util.Arrays.*;
19-
import static org.mockito.Mockito.*;
20-
21-
import java.util.HashSet;
18+
import static java.util.Arrays.asList;
19+
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
20+
import static org.mockito.Mockito.mock;
21+
import static org.mockito.Mockito.verify;
22+
import static org.mockito.Mockito.when;
2223

2324
import jakarta.persistence.EntityGraph;
2425
import jakarta.persistence.EntityManager;
2526
import jakarta.persistence.Subgraph;
2627

28+
import java.util.HashSet;
29+
2730
import org.junit.jupiter.api.BeforeEach;
2831
import org.junit.jupiter.api.Test;
2932

3033
/**
3134
* Unit tests for {@link EntityGraphFactory}.
3235
*
3336
* @author Jens Schauder
37+
* @author Petr Strnad
3438
*/
3539
@SuppressWarnings("rawtypes")
3640
class EntityGraphFactoryUnitTests {
@@ -45,8 +49,7 @@ void beforeEach() {
4549
when(em.createEntityGraph(DummyEntity.class)).thenReturn(entityGraph);
4650
}
4751

48-
// GH-2329
49-
@Test
52+
@Test // GH-2329
5053
void simpleSetOfPropertiesGetRegistered() {
5154

5255
HashSet<String> properties = new HashSet<>(asList("one", "two"));
@@ -57,8 +60,7 @@ void simpleSetOfPropertiesGetRegistered() {
5760
verify(entityGraph).addAttributeNodes("two");
5861
}
5962

60-
// GH-2329
61-
@Test
63+
@Test // GH-2329
6264
void setOfCompositePropertiesGetRegisteredPiecewise() {
6365

6466
HashSet<String> properties = new HashSet<>(asList("one.two", "eins.zwei.drei"));
@@ -76,6 +78,19 @@ void setOfCompositePropertiesGetRegisteredPiecewise() {
7678
verify(zwei).addAttributeNodes("drei");
7779
}
7880

81+
@Test // GH-2571
82+
void multipleSubNodesUnderSameParentNodeShouldWork() {
83+
84+
HashSet<String> properties = new HashSet<>(asList("one.one", "one.two"));
85+
86+
entityGraph = EntityGraphFactory.create(em, DummyEntity.class, properties);
87+
88+
verify(entityGraph).addSubgraph("one");
89+
Subgraph<?> one = entityGraph.addSubgraph("one");
90+
verify(one).addAttributeNodes("one");
91+
verify(one).addAttributeNodes("two");
92+
}
93+
7994
private static class DummyEntity {
8095
DummyEntity one;
8196
DummyEntity two;

0 commit comments

Comments
 (0)