Skip to content

Commit ade0530

Browse files
committed
Setting most generic class for source of relationship
resolves spring-projects#2526
1 parent 103c3c2 commit ade0530

File tree

8 files changed

+164
-36
lines changed

8 files changed

+164
-36
lines changed

src/main/java/org/springframework/data/neo4j/core/mapping/DefaultRelationshipDescription.java

+19-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
/**
2525
* @author Michael J. Simons
2626
* @author Gerrit Meier
27+
* @author Andreas Berger
2728
* @since 6.0
2829
*/
2930
final class DefaultRelationshipDescription extends Association<Neo4jPersistentProperty> implements RelationshipDescription {
@@ -55,13 +56,30 @@ final class DefaultRelationshipDescription extends Association<Neo4jPersistentPr
5556
this.relationshipObverse = relationshipObverse;
5657
this.type = type;
5758
this.dynamic = dynamic;
58-
this.source = source;
59+
this.source = getSourceForField(source, type, dynamic, target, direction, relationshipProperties);
5960
this.fieldName = fieldName;
6061
this.target = target;
6162
this.direction = direction;
6263
this.relationshipPropertiesClass = relationshipProperties;
6364
}
6465

66+
private static NodeDescription<?> getSourceForField(NodeDescription<?> source, String type, boolean dynamic,
67+
NodeDescription<?> target, Relationship.Direction direction,
68+
@Nullable NodeDescription<?> relationshipProperties) {
69+
NodeDescription<?> parent = source.getParentNodeDescription();
70+
if (parent == null) {
71+
return source;
72+
}
73+
for (RelationshipDescription relationship : parent.getRelationships()) {
74+
if (Objects.equals(relationship.getTarget(), target) && Objects.equals(relationship.getDirection(), direction)
75+
&& Objects.equals(relationship.isDynamic(), dynamic) && Objects.equals(relationship.getType(), type)
76+
&& Objects.equals(relationship.getRelationshipPropertiesEntity(), relationshipProperties)) {
77+
return getSourceForField(relationship.getSource(), type, dynamic, target, direction, relationshipProperties);
78+
}
79+
}
80+
return source;
81+
}
82+
6583
@Override
6684
public String getType() {
6785
return type;
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,36 @@
1+
/*
2+
* Copyright 2011-2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
116
package org.springframework.data.neo4j.integration.issues.gh2526;
217

3-
import lombok.*;
18+
import static org.springframework.data.neo4j.core.schema.Relationship.Direction.*;
19+
20+
import lombok.AccessLevel;
21+
import lombok.AllArgsConstructor;
22+
import lombok.Data;
23+
import lombok.EqualsAndHashCode;
24+
import lombok.NoArgsConstructor;
25+
import lombok.Setter;
426
import lombok.experimental.SuperBuilder;
27+
528
import org.springframework.data.neo4j.core.schema.Node;
629
import org.springframework.data.neo4j.core.schema.Relationship;
730

8-
import static org.springframework.data.neo4j.core.schema.Relationship.Direction.OUTGOING;
9-
31+
/**
32+
* @author Andreas Berger
33+
*/
1034
@Node
1135
@Data
1236
@Setter(AccessLevel.PRIVATE)
@@ -18,6 +42,5 @@ public class AccountingMeasurementMeta extends MeasurementMeta {
1842

1943
private String formula;
2044

21-
@Relationship(type = "WEIGHTS", direction = OUTGOING)
22-
private MeasurementMeta baseMeasurement;
45+
@Relationship(type = "WEIGHTS", direction = OUTGOING) private MeasurementMeta baseMeasurement;
2346
}

src/test/java/org/springframework/data/neo4j/integration/issues/gh2526/BaseNodeEntity.java

+26-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,36 @@
1+
/*
2+
* Copyright 2011-2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
116
package org.springframework.data.neo4j.integration.issues.gh2526;
217

3-
import lombok.*;
18+
import lombok.AccessLevel;
19+
import lombok.AllArgsConstructor;
20+
import lombok.Data;
21+
import lombok.EqualsAndHashCode;
22+
import lombok.NoArgsConstructor;
23+
import lombok.Setter;
424
import lombok.experimental.NonFinal;
525
import lombok.experimental.SuperBuilder;
26+
627
import org.springframework.data.neo4j.core.schema.GeneratedValue;
728
import org.springframework.data.neo4j.core.schema.Id;
829
import org.springframework.data.neo4j.core.support.UUIDStringGenerator;
930

31+
/**
32+
* @author Andreas Berger
33+
*/
1034
@org.springframework.data.neo4j.core.schema.Node
1135
@NonFinal
1236
@Data
@@ -19,6 +43,5 @@ public class BaseNodeEntity {
1943

2044
@Id
2145
@GeneratedValue(UUIDStringGenerator.class)
22-
@EqualsAndHashCode.Include
23-
private String nodeId;
46+
@EqualsAndHashCode.Include private String nodeId;
2447
}

src/test/java/org/springframework/data/neo4j/integration/issues/gh2526/BaseNodeRepository.java

+3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717

1818
import org.springframework.data.neo4j.repository.Neo4jRepository;
1919

20+
/**
21+
* @author Andreas Berger
22+
*/
2023
public interface BaseNodeRepository extends Neo4jRepository<BaseNodeEntity, String> {
2124

2225
<R> R findByNodeId(String nodeIds, Class<R> clazz);
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,33 @@
1+
/*
2+
* Copyright 2011-2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
116
package org.springframework.data.neo4j.integration.issues.gh2526;
217

318
import lombok.AllArgsConstructor;
419
import lombok.EqualsAndHashCode;
520
import lombok.Value;
621
import lombok.With;
22+
723
import org.springframework.data.annotation.Immutable;
824
import org.springframework.data.neo4j.core.schema.RelationshipId;
925
import org.springframework.data.neo4j.core.schema.RelationshipProperties;
1026
import org.springframework.data.neo4j.core.schema.TargetNode;
1127

28+
/**
29+
* @author Andreas Berger
30+
*/
1231
@RelationshipProperties
1332
@Value
1433
@With
@@ -17,12 +36,10 @@
1736
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
1837
public class DataPoint {
1938

20-
@RelationshipId
21-
Long id;
39+
@RelationshipId Long id;
2240

2341
boolean manual;
2442

2543
@TargetNode
26-
@EqualsAndHashCode.Include
27-
Measurand measurand;
44+
@EqualsAndHashCode.Include Measurand measurand;
2845
}

src/test/java/org/springframework/data/neo4j/integration/issues/gh2526/GH2526.java renamed to src/test/java/org/springframework/data/neo4j/integration/issues/gh2526/GH2526IT.java

+18-15
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
*/
1616
package org.springframework.data.neo4j.integration.issues.gh2526;
1717

18+
import static org.assertj.core.api.Assertions.*;
19+
import static org.assertj.core.api.InstanceOfAssertFactories.*;
20+
1821
import java.util.Set;
1922

2023
import org.junit.jupiter.api.BeforeEach;
@@ -35,10 +38,11 @@
3538
import org.springframework.transaction.PlatformTransactionManager;
3639
import org.springframework.transaction.annotation.EnableTransactionManagement;
3740

38-
import static org.assertj.core.api.Assertions.assertThat;
39-
41+
/**
42+
* @author Andreas Berger
43+
*/
4044
@Neo4jIntegrationTest
41-
public class GH2526 {
45+
public class GH2526IT {
4246

4347
protected static Neo4jExtension.Neo4jConnectionSupport neo4jConnectionSupport;
4448

@@ -47,27 +51,28 @@ void setupData(@Autowired Driver driver, @Autowired BookmarkCapture bookmarkCapt
4751

4852
try (Session session = driver.session()) {
4953
session.run("MATCH (n) DETACH DELETE n").consume();
50-
session.run(
51-
"CREATE (o1:Measurand {measurandId: 'o1'})" +
52-
"CREATE (acc1:AccountingMeasurementMeta:BaseNodeEntity {nodeId: 'acc1'})" +
53-
"CREATE (o1)-[:IS_MEASURED_BY{ manual: true }]->(acc1)"
54-
).consume();
54+
session.run("CREATE (o1:Measurand {measurandId: 'o1'})"
55+
+ "CREATE (acc1:AccountingMeasurementMeta:BaseNodeEntity {nodeId: 'acc1'})"
56+
+ "CREATE (o1)-[:IS_MEASURED_BY{ manual: true }]->(acc1)").consume();
5557
bookmarkCapture.seedWith(session.lastBookmark());
5658
}
5759
}
5860

5961
@Test
60-
void test(@Autowired BaseNodeRepository repository) {
62+
// GH-2526
63+
void testRichRelationWithInheritance(@Autowired BaseNodeRepository repository) {
6164
Projection m = repository.findByNodeId("acc1", Projection.class);
6265
assertThat(m).isNotNull();
66+
assertThat(m).extracting(Projection::getDataPoints, collection(DataPoint.class))
67+
.extracting(DataPoint::isManual, DataPoint::getMeasurand).contains(tuple(true, new Measurand("o1")));
6368
}
6469

6570
interface Projection {
6671
String getNodeId();
72+
6773
Set<DataPoint> getDataPoints();
6874
}
6975

70-
7176
@Configuration
7277
@EnableTransactionManagement
7378
@EnableNeo4jRepositories
@@ -79,13 +84,11 @@ public BookmarkCapture bookmarkCapture() {
7984
}
8085

8186
@Override
82-
public PlatformTransactionManager transactionManager(
83-
Driver driver, DatabaseSelectionProvider databaseNameProvider)
84-
{
87+
public PlatformTransactionManager transactionManager(Driver driver,
88+
DatabaseSelectionProvider databaseNameProvider) {
8589

8690
BookmarkCapture bookmarkCapture = bookmarkCapture();
87-
return new Neo4jTransactionManager(driver, databaseNameProvider,
88-
Neo4jBookmarkManager.create(bookmarkCapture));
91+
return new Neo4jTransactionManager(driver, databaseNameProvider, Neo4jBookmarkManager.create(bookmarkCapture));
8992
}
9093

9194
@Bean
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,35 @@
1+
/*
2+
* Copyright 2011-2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
116
package org.springframework.data.neo4j.integration.issues.gh2526;
217

318
import lombok.AllArgsConstructor;
419
import lombok.Value;
20+
521
import org.springframework.data.annotation.Immutable;
622
import org.springframework.data.neo4j.core.schema.Id;
723
import org.springframework.data.neo4j.core.schema.Node;
824

25+
/**
26+
* @author Andreas Berger
27+
*/
928
@Node
1029
@Value
1130
@AllArgsConstructor
1231
@Immutable
1332
public class Measurand {
1433

15-
@Id
16-
String measurandId;
34+
@Id String measurandId;
1735
}
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,37 @@
1+
/*
2+
* Copyright 2011-2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
116
package org.springframework.data.neo4j.integration.issues.gh2526;
217

3-
import java.util.Set;
18+
import static org.springframework.data.neo4j.core.schema.Relationship.Direction.*;
419

5-
import lombok.*;
20+
import lombok.AccessLevel;
21+
import lombok.AllArgsConstructor;
22+
import lombok.Data;
23+
import lombok.EqualsAndHashCode;
24+
import lombok.NoArgsConstructor;
25+
import lombok.Setter;
626
import lombok.experimental.SuperBuilder;
7-
import org.springframework.data.neo4j.core.schema.Relationship;
827

9-
import static org.springframework.data.neo4j.core.schema.Relationship.Direction.INCOMING;
28+
import java.util.Set;
29+
30+
import org.springframework.data.neo4j.core.schema.Relationship;
1031

32+
/**
33+
* @author Andreas Berger
34+
*/
1135
@org.springframework.data.neo4j.core.schema.Node
1236
@Data
1337
@Setter(AccessLevel.PRIVATE)
@@ -17,6 +41,5 @@
1741
@SuperBuilder(toBuilder = true)
1842
public class MeasurementMeta extends BaseNodeEntity {
1943

20-
@Relationship(type = "IS_MEASURED_BY", direction = INCOMING)
21-
private Set<DataPoint> dataPoints;
44+
@Relationship(type = "IS_MEASURED_BY", direction = INCOMING) private Set<DataPoint> dataPoints;
2245
}

0 commit comments

Comments
 (0)