Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit dec5533

Browse files
GH-3036 - Use correct type for mapping.
If there is a class hierarchy scenario, SDN will try to use the best matching child class. In some cases the parent, non-abstract class is already the best fit and should be used. Closes #3036 Signed-off-by: Gerrit Meier <meistermeier@gmail.com>
1 parent 47d8a98 commit dec5533

File tree

6 files changed

+177
-5
lines changed

6 files changed

+177
-5
lines changed

‎src/main/java/org/springframework/data/neo4j/core/mapping/NodeDescriptionStore.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,8 @@ NodeDescriptionAndLabels deriveConcreteNodeDescription(NodeDescription<?> entity
108108
private NodeDescriptionAndLabels computeConcreteNodeDescription(NodeDescription<?> entityDescription,
109109
List<String> labels) {
110110

111-
booleanisConcreteClassThatFulfillsEverything = !Modifier
112-
.isAbstract(entityDescription.getUnderlyingClass().getModifiers())
111+
varisAbstractClassOrInterface = Modifier.isAbstract(entityDescription.getUnderlyingClass().getModifiers());
112+
booleanisConcreteClassThatFulfillsEverything = !isAbstractClassOrInterface
113113
&& entityDescription.getStaticLabels().containsAll(labels);
114114

115115
if (labels == null || labels.isEmpty() || isConcreteClassThatFulfillsEverything) {
@@ -126,9 +126,13 @@ private NodeDescriptionAndLabels computeConcreteNodeDescription(NodeDescription<
126126

127127
if (!haystack.isEmpty()) {
128128

129-
NodeDescription<?> mostMatchingNodeDescription = null;
129+
NodeDescription<?> mostMatchingNodeDescription = !isAbstractClassOrInterface ? entityDescription : null;
130+
List<String> mostMatchingStaticLabels = !isAbstractClassOrInterface ? entityDescription.getStaticLabels()
131+
: List.of();
130132
Map<NodeDescription<?>, Integer> unmatchedLabelsCache = new HashMap<>();
131-
List<String> mostMatchingStaticLabels = null;
133+
if (!isAbstractClassOrInterface) {
134+
unmatchedLabelsCache.put(mostMatchingNodeDescription, labels.size() - mostMatchingStaticLabels.size());
135+
}
132136

133137
for (NodeDescription<?> nd : haystack) {
134138

@@ -164,7 +168,7 @@ private NodeDescriptionAndLabels computeConcreteNodeDescription(NodeDescription<
164168
}
165169

166170
Set<String> surplusLabels = new HashSet<>(labels);
167-
if (mostMatchingStaticLabels != null) {
171+
if (!mostMatchingStaticLabels.isEmpty()) {
168172
mostMatchingStaticLabels.forEach(surplusLabels::remove);
169173
}
170174
if (mostMatchingNodeDescription == null) {

‎src/test/java/org/springframework/data/neo4j/integration/issues/IssuesIT.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,8 @@
199199
import org.springframework.data.neo4j.integration.issues.gh2973.RelationshipB;
200200
import org.springframework.data.neo4j.integration.issues.gh2973.RelationshipC;
201201
import org.springframework.data.neo4j.integration.issues.gh2973.RelationshipD;
202+
import org.springframework.data.neo4j.integration.issues.gh3036.Vehicle;
203+
import org.springframework.data.neo4j.integration.issues.gh3036.VehicleRepository;
202204
import org.springframework.data.neo4j.integration.issues.qbe.A;
203205
import org.springframework.data.neo4j.integration.issues.qbe.ARepository;
204206
import org.springframework.data.neo4j.integration.issues.qbe.B;
@@ -1854,6 +1856,23 @@ void abstractedRelationshipTypesShouldBeMappedCorrectly(@Autowired Gh2973Reposit
18541856
assertThat(relationshipsCFail.get(0)).isNotExactlyInstanceOf(BaseRelationship.class);
18551857
}
18561858

1859+
@Tag("GH-3036")
1860+
@Test
1861+
void asdf(@Autowired VehicleRepository repository) {
1862+
var vehicleWithoutDynamicLabels = new Vehicle();
1863+
var vehicleWithOneDynamicLabel = new Vehicle();
1864+
vehicleWithOneDynamicLabel.setLabels(Set.of("label1"));
1865+
var vehicleWithTwoDynamicLabels = new Vehicle();
1866+
vehicleWithTwoDynamicLabels.setLabels(Set.of("label1", "label2"));
1867+
1868+
repository
1869+
.saveAll(List.of(vehicleWithoutDynamicLabels, vehicleWithOneDynamicLabel, vehicleWithTwoDynamicLabels));
1870+
1871+
var vehicles = repository.findAllVehicles();
1872+
assertThat(vehicles).hasOnlyElementsOfType(Vehicle.class);
1873+
1874+
}
1875+
18571876
@Configuration
18581877
@EnableTransactionManagement
18591878
@EnableNeo4jRepositories(namedQueriesLocation = "more-custom-queries.properties")
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Copyright 2011-2025 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+
*/
16+
package org.springframework.data.neo4j.integration.issues.gh3036;
17+
18+
import org.springframework.data.neo4j.core.schema.Node;
19+
20+
/**
21+
* Detailed implementation candidate
22+
*/
23+
@Node(primaryLabel = "Car")
24+
public class Car extends Vehicle {
25+
26+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Copyright 2011-2025 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+
*/
16+
package org.springframework.data.neo4j.integration.issues.gh3036;
17+
18+
import org.springframework.data.neo4j.core.schema.Node;
19+
20+
/**
21+
* Detailed implementation candidate
22+
*/
23+
@Node(primaryLabel = "Sedan")
24+
public class Sedan extends Car {
25+
26+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Copyright 2011-2025 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+
*/
16+
package org.springframework.data.neo4j.integration.issues.gh3036;
17+
18+
import java.util.Set;
19+
20+
import org.springframework.data.neo4j.core.schema.DynamicLabels;
21+
import org.springframework.data.neo4j.core.schema.GeneratedValue;
22+
import org.springframework.data.neo4j.core.schema.Id;
23+
import org.springframework.data.neo4j.core.schema.Node;
24+
import org.springframework.data.neo4j.core.schema.Property;
25+
26+
/**
27+
* Parent class
28+
*/
29+
@Node(primaryLabel = "Vehicle")
30+
public class Vehicle {
31+
32+
@Id
33+
@GeneratedValue
34+
public String id;
35+
36+
@Property(name = "name")
37+
public String name;
38+
39+
@DynamicLabels
40+
public Set<String> labels = Set.of();
41+
42+
public String getId() {
43+
return this.id;
44+
}
45+
46+
public void setId(String id) {
47+
this.id = id;
48+
}
49+
50+
public Set<String> getLabels() {
51+
return this.labels;
52+
}
53+
54+
public void setLabels(Set<String> labels) {
55+
this.labels = labels;
56+
}
57+
58+
public String getName() {
59+
return this.name;
60+
}
61+
62+
public void setName(String name) {
63+
this.name = name;
64+
}
65+
66+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright 2011-2025 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+
*/
16+
package org.springframework.data.neo4j.integration.issues.gh3036;
17+
18+
import java.util.List;
19+
20+
import org.springframework.data.neo4j.repository.Neo4jRepository;
21+
import org.springframework.data.neo4j.repository.query.Query;
22+
23+
/**
24+
* Repository for testing GH-3036
25+
*/
26+
public interface VehicleRepository extends Neo4jRepository<Vehicle, String> {
27+
28+
@Query("MATCH (vehicle:Vehicle) RETURN vehicle")
29+
List<Vehicle> findAllVehicles();
30+
31+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /