Skip to content

Commit fa43d68

Browse files
GH-2296 - Convert Ids before determining dynamic labels.
Fixes #2296.
1 parent 39d99da commit fa43d68

File tree

5 files changed

+119
-2
lines changed

5 files changed

+119
-2
lines changed

src/main/java/org/springframework/data/neo4j/core/Neo4jTemplate.java

+6-1
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,10 @@ entityMetaData, convertIdValues(entityMetaData.getRequiredIdProperty(), ids)))
217217

218218
private Object convertIdValues(@Nullable Neo4jPersistentProperty idProperty, Object idValues) {
219219

220+
if (((Neo4jPersistentEntity<?>) idProperty.getOwner()).isUsingInternalIds()) {
221+
return idValues;
222+
}
223+
220224
return neo4jMappingContext.getConversionService().writeValue(idValues,
221225
ClassTypeInformation.from(idValues.getClass()),
222226
idProperty == null ? null : idProperty.getOptionalWritingConverter());
@@ -269,9 +273,10 @@ private <T> DynamicLabels determineDynamicLabels(T entityToBeSaved, Neo4jPersist
269273
return entityMetaData.getDynamicLabelsProperty().map(p -> {
270274

271275
PersistentPropertyAccessor propertyAccessor = entityMetaData.getPropertyAccessor(entityToBeSaved);
276+
Neo4jPersistentProperty idProperty = entityMetaData.getRequiredIdProperty();
272277
Neo4jClient.RunnableSpecTightToDatabase runnableQuery = neo4jClient
273278
.query(() -> renderer.render(cypherGenerator.createStatementReturningDynamicLabels(entityMetaData)))
274-
.in(inDatabase).bind(propertyAccessor.getProperty(entityMetaData.getRequiredIdProperty()))
279+
.in(inDatabase).bind(convertIdValues(idProperty, propertyAccessor.getProperty(idProperty)))
275280
.to(Constants.NAME_OF_ID).bind(entityMetaData.getStaticLabels())
276281
.to(Constants.NAME_OF_STATIC_LABELS_PARAM);
277282

src/main/java/org/springframework/data/neo4j/core/ReactiveNeo4jTemplate.java

+6-1
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,10 @@ public <T> Mono<ExecutableQuery<T>> toExecutableQuery(Class<T> domainType,
220220

221221
private Object convertIdValues(@Nullable Neo4jPersistentProperty idProperty, Object idValues) {
222222

223+
if (((Neo4jPersistentEntity<?>) idProperty.getOwner()).isUsingInternalIds()) {
224+
return idValues;
225+
}
226+
223227
return neo4jMappingContext.getConversionService().writeValue(idValues,
224228
ClassTypeInformation.from(idValues.getClass()), idProperty == null ? null : idProperty.getOptionalWritingConverter());
225229
}
@@ -267,9 +271,10 @@ private <T> Mono<Tuple2<T, DynamicLabels>> determineDynamicLabels(T entityToBeSa
267271
return entityMetaData.getDynamicLabelsProperty().map(p -> {
268272

269273
PersistentPropertyAccessor propertyAccessor = entityMetaData.getPropertyAccessor(entityToBeSaved);
274+
Neo4jPersistentProperty idProperty = entityMetaData.getRequiredIdProperty();
270275
ReactiveNeo4jClient.RunnableSpecTightToDatabase runnableQuery = neo4jClient
271276
.query(() -> renderer.render(cypherGenerator.createStatementReturningDynamicLabels(entityMetaData)))
272-
.in(inDatabase).bind(propertyAccessor.getProperty(entityMetaData.getRequiredIdProperty()))
277+
.in(inDatabase).bind(convertIdValues(idProperty, propertyAccessor.getProperty(idProperty)))
273278
.to(Constants.NAME_OF_ID).bind(entityMetaData.getStaticLabels()).to(Constants.NAME_OF_STATIC_LABELS_PARAM);
274279

275280
if (entityMetaData.hasVersionProperty()) {

src/test/java/org/springframework/data/neo4j/integration/imperative/DynamicLabelsIT.java

+15
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
import org.springframework.data.neo4j.integration.shared.common.EntitiesWithDynamicLabels.SimpleDynamicLabelsWithBusinessIdAndVersion;
5555
import org.springframework.data.neo4j.integration.shared.common.EntitiesWithDynamicLabels.SimpleDynamicLabelsWithVersion;
5656
import org.springframework.data.neo4j.integration.shared.common.EntitiesWithDynamicLabels.SuperNode;
57+
import org.springframework.data.neo4j.integration.shared.common.EntityWithDynamicLabelsAndIdThatNeedsToBeConverted;
5758
import org.springframework.data.neo4j.test.Neo4jExtension;
5859
import org.springframework.test.context.ContextConfiguration;
5960
import org.springframework.test.context.junit.jupiter.SpringExtension;
@@ -357,6 +358,20 @@ void shouldReadDynamicLabelsOnClassWithMultipleNodeLabel(@Autowired Neo4jTemplat
357358
entity -> assertThat(entity.moreLabels).containsExactlyInAnyOrder("SimpleDynamicLabels", "Baz", "Foobar"));
358359
}
359360

361+
@Test // GH-2296
362+
void shouldConvertIds(@Autowired Neo4jTemplate template) {
363+
364+
template.deleteAll(EntityWithDynamicLabelsAndIdThatNeedsToBeConverted.class);
365+
EntityWithDynamicLabelsAndIdThatNeedsToBeConverted savedInstance = template
366+
.save(new EntityWithDynamicLabelsAndIdThatNeedsToBeConverted("value_1"));
367+
368+
assertThat(savedInstance.getValue()).isEqualTo("value_1");
369+
assertThat(savedInstance.getExtraLabels()).containsExactlyInAnyOrder("value_1");
370+
371+
Optional<EntityWithDynamicLabelsAndIdThatNeedsToBeConverted> optionalReloadedInstance =
372+
template.findById(savedInstance.getId(), EntityWithDynamicLabelsAndIdThatNeedsToBeConverted.class);
373+
assertThat(optionalReloadedInstance).hasValueSatisfying(v -> v.getExtraLabels().contains("value_1"));
374+
}
360375
}
361376

362377
@Nested

src/test/java/org/springframework/data/neo4j/integration/reactive/ReactiveDynamicLabelsIT.java

+24
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
import java.util.Collections;
2727
import java.util.HashSet;
2828
import java.util.UUID;
29+
import java.util.concurrent.atomic.AtomicReference;
30+
import java.util.function.Predicate;
2931

3032
import org.junit.jupiter.api.BeforeEach;
3133
import org.junit.jupiter.api.Nested;
@@ -56,6 +58,7 @@
5658
import org.springframework.data.neo4j.integration.shared.common.EntitiesWithDynamicLabels.SimpleDynamicLabelsWithBusinessIdAndVersion;
5759
import org.springframework.data.neo4j.integration.shared.common.EntitiesWithDynamicLabels.SimpleDynamicLabelsWithVersion;
5860
import org.springframework.data.neo4j.integration.shared.common.EntitiesWithDynamicLabels.SuperNode;
61+
import org.springframework.data.neo4j.integration.shared.common.EntityWithDynamicLabelsAndIdThatNeedsToBeConverted;
5962
import org.springframework.data.neo4j.test.Neo4jExtension;
6063
import org.springframework.test.context.ContextConfiguration;
6164
import org.springframework.test.context.junit.jupiter.SpringExtension;
@@ -349,6 +352,27 @@ void shouldReadDynamicLabelsOnClassWithMultipleNodeLabel(@Autowired ReactiveNeo4
349352
.flatMapMany(entity -> Flux.fromIterable(entity.moreLabels)).sort().as(StepVerifier::create)
350353
.expectNext("Baz", "Foobar", "SimpleDynamicLabels");
351354
}
355+
356+
@Test // GH-2296
357+
void shouldConvertIds(@Autowired ReactiveNeo4jTemplate template) {
358+
359+
String label = "value_1";
360+
Predicate<EntityWithDynamicLabelsAndIdThatNeedsToBeConverted> expectatations = savedInstance ->
361+
label.equals(savedInstance.getValue()) && savedInstance.getExtraLabels().contains(label);
362+
363+
AtomicReference<UUID> generatedUUID = new AtomicReference<>();
364+
template.deleteAll(EntityWithDynamicLabelsAndIdThatNeedsToBeConverted.class)
365+
.then(template.save(new EntityWithDynamicLabelsAndIdThatNeedsToBeConverted(label)))
366+
.doOnNext(s -> generatedUUID.set(s.getId()))
367+
.as(StepVerifier::create)
368+
.expectNextMatches(expectatations)
369+
.verifyComplete();
370+
371+
template.findById(generatedUUID.get(), EntityWithDynamicLabelsAndIdThatNeedsToBeConverted.class)
372+
.as(StepVerifier::create)
373+
.expectNextMatches(expectatations)
374+
.verifyComplete();
375+
}
352376
}
353377

354378
@Nested
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
* Copyright 2011-2021 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.shared.common;
17+
18+
import java.util.HashSet;
19+
import java.util.Objects;
20+
import java.util.Set;
21+
import java.util.UUID;
22+
23+
import org.springframework.data.neo4j.core.schema.DynamicLabels;
24+
import org.springframework.data.neo4j.core.schema.GeneratedValue;
25+
import org.springframework.data.neo4j.core.schema.Id;
26+
import org.springframework.data.neo4j.core.schema.Node;
27+
28+
/**
29+
* Provided via Github as reproducer for entities with dynamic labels and ids that are subject to conversion. Needed for GH-2296.
30+
*
31+
* @author Michael J. Simons
32+
*/
33+
@Node
34+
public class EntityWithDynamicLabelsAndIdThatNeedsToBeConverted {
35+
@Id
36+
@GeneratedValue
37+
private UUID id;
38+
39+
@DynamicLabels
40+
private Set<String> extraLabels;
41+
42+
private String value;
43+
44+
public EntityWithDynamicLabelsAndIdThatNeedsToBeConverted(String value) {
45+
setValue(value);
46+
}
47+
48+
public void setValue(String value) {
49+
this.value = value;
50+
51+
if (Objects.isNull(extraLabels)) {
52+
extraLabels = new HashSet<>();
53+
}
54+
extraLabels.add(value);
55+
}
56+
57+
public String getValue() {
58+
return value;
59+
}
60+
61+
public Set<String> getExtraLabels() {
62+
return extraLabels;
63+
}
64+
65+
public UUID getId() {
66+
return id;
67+
}
68+
}

0 commit comments

Comments
 (0)