Skip to content

Commit bbc03ae

Browse files
GH-2296 - Convert Ids before determining dynamic labels.
Fixes #2296.
1 parent 1503acd commit bbc03ae

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,10 @@ entityMetaData, convertIdValues(entityMetaData.getRequiredIdProperty(), ids)))
300300

301301
private Object convertIdValues(@Nullable Neo4jPersistentProperty idProperty, Object idValues) {
302302

303+
if (((Neo4jPersistentEntity<?>) idProperty.getOwner()).isUsingInternalIds()) {
304+
return idValues;
305+
}
306+
303307
return neo4jMappingContext.getConversionService().writeValue(idValues,
304308
ClassTypeInformation.from(idValues.getClass()),
305309
idProperty == null ? null : idProperty.getOptionalWritingConverter());
@@ -388,9 +392,10 @@ private <T> DynamicLabels determineDynamicLabels(T entityToBeSaved, Neo4jPersist
388392
return entityMetaData.getDynamicLabelsProperty().map(p -> {
389393

390394
PersistentPropertyAccessor<T> propertyAccessor = entityMetaData.getPropertyAccessor(entityToBeSaved);
395+
Neo4jPersistentProperty idProperty = entityMetaData.getRequiredIdProperty();
391396
Neo4jClient.RunnableSpecTightToDatabase runnableQuery = neo4jClient
392397
.query(() -> renderer.render(cypherGenerator.createStatementReturningDynamicLabels(entityMetaData)))
393-
.bind(propertyAccessor.getProperty(entityMetaData.getRequiredIdProperty()))
398+
.bind(convertIdValues(idProperty, propertyAccessor.getProperty(idProperty)))
394399
.to(Constants.NAME_OF_ID).bind(entityMetaData.getStaticLabels())
395400
.to(Constants.NAME_OF_STATIC_LABELS_PARAM);
396401

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,10 @@ public <T> Mono<ExecutableQuery<T>> toExecutableQuery(Class<T> domainType,
284284

285285
private Object convertIdValues(@Nullable Neo4jPersistentProperty idProperty, Object idValues) {
286286

287+
if (((Neo4jPersistentEntity<?>) idProperty.getOwner()).isUsingInternalIds()) {
288+
return idValues;
289+
}
290+
287291
return neo4jMappingContext.getConversionService().writeValue(idValues,
288292
ClassTypeInformation.from(idValues.getClass()), idProperty == null ? null : idProperty.getOptionalWritingConverter());
289293
}
@@ -379,9 +383,10 @@ private <T> Mono<Tuple2<T, DynamicLabels>> determineDynamicLabels(T entityToBeSa
379383
return entityMetaData.getDynamicLabelsProperty().map(p -> {
380384

381385
PersistentPropertyAccessor propertyAccessor = entityMetaData.getPropertyAccessor(entityToBeSaved);
386+
Neo4jPersistentProperty idProperty = entityMetaData.getRequiredIdProperty();
382387
ReactiveNeo4jClient.RunnableSpecTightToDatabase runnableQuery = neo4jClient
383388
.query(() -> renderer.render(cypherGenerator.createStatementReturningDynamicLabels(entityMetaData)))
384-
.bind(propertyAccessor.getProperty(entityMetaData.getRequiredIdProperty()))
389+
.bind(convertIdValues(idProperty, propertyAccessor.getProperty(idProperty)))
385390
.to(Constants.NAME_OF_ID).bind(entityMetaData.getStaticLabels()).to(Constants.NAME_OF_STATIC_LABELS_PARAM);
386391

387392
if (entityMetaData.hasVersionProperty()) {

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
import org.springframework.data.neo4j.integration.shared.common.EntitiesWithDynamicLabels.SimpleDynamicLabelsWithBusinessIdAndVersion;
5959
import org.springframework.data.neo4j.integration.shared.common.EntitiesWithDynamicLabels.SimpleDynamicLabelsWithVersion;
6060
import org.springframework.data.neo4j.integration.shared.common.EntitiesWithDynamicLabels.SuperNode;
61+
import org.springframework.data.neo4j.integration.shared.common.EntityWithDynamicLabelsAndIdThatNeedsToBeConverted;
6162
import org.springframework.data.neo4j.test.BookmarkCapture;
6263
import org.springframework.data.neo4j.test.Neo4jExtension;
6364
import org.springframework.test.annotation.DirtiesContext;
@@ -393,6 +394,20 @@ void shouldReadDynamicLabelsOnClassWithMultipleNodeLabel(@Autowired Neo4jTemplat
393394
entity -> assertThat(entity.moreLabels).containsExactlyInAnyOrder("SimpleDynamicLabels", "Baz", "Foobar"));
394395
}
395396

397+
@Test // GH-2296
398+
void shouldConvertIds(@Autowired Neo4jTemplate template) {
399+
400+
template.deleteAll(EntityWithDynamicLabelsAndIdThatNeedsToBeConverted.class);
401+
EntityWithDynamicLabelsAndIdThatNeedsToBeConverted savedInstance = template
402+
.save(new EntityWithDynamicLabelsAndIdThatNeedsToBeConverted("value_1"));
403+
404+
assertThat(savedInstance.getValue()).isEqualTo("value_1");
405+
assertThat(savedInstance.getExtraLabels()).containsExactlyInAnyOrder("value_1");
406+
407+
Optional<EntityWithDynamicLabelsAndIdThatNeedsToBeConverted> optionalReloadedInstance =
408+
template.findById(savedInstance.getId(), EntityWithDynamicLabelsAndIdThatNeedsToBeConverted.class);
409+
assertThat(optionalReloadedInstance).hasValueSatisfying(v -> v.getExtraLabels().contains("value_1"));
410+
}
396411
}
397412

398413
@Nested

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

Lines changed: 24 additions & 0 deletions
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;
@@ -59,6 +61,7 @@
5961
import org.springframework.data.neo4j.integration.shared.common.EntitiesWithDynamicLabels.SimpleDynamicLabelsWithBusinessIdAndVersion;
6062
import org.springframework.data.neo4j.integration.shared.common.EntitiesWithDynamicLabels.SimpleDynamicLabelsWithVersion;
6163
import org.springframework.data.neo4j.integration.shared.common.EntitiesWithDynamicLabels.SuperNode;
64+
import org.springframework.data.neo4j.integration.shared.common.EntityWithDynamicLabelsAndIdThatNeedsToBeConverted;
6265
import org.springframework.data.neo4j.test.BookmarkCapture;
6366
import org.springframework.data.neo4j.test.Neo4jExtension;
6467
import org.springframework.test.annotation.DirtiesContext;
@@ -372,6 +375,27 @@ void shouldReadDynamicLabelsOnClassWithMultipleNodeLabel(@Autowired ReactiveNeo4
372375
.flatMapMany(entity -> Flux.fromIterable(entity.moreLabels)).sort().as(StepVerifier::create)
373376
.expectNext("Baz", "Foobar", "SimpleDynamicLabels");
374377
}
378+
379+
@Test // GH-2296
380+
void shouldConvertIds(@Autowired ReactiveNeo4jTemplate template) {
381+
382+
String label = "value_1";
383+
Predicate<EntityWithDynamicLabelsAndIdThatNeedsToBeConverted> expectatations = savedInstance ->
384+
label.equals(savedInstance.getValue()) && savedInstance.getExtraLabels().contains(label);
385+
386+
AtomicReference<UUID> generatedUUID = new AtomicReference<>();
387+
template.deleteAll(EntityWithDynamicLabelsAndIdThatNeedsToBeConverted.class)
388+
.then(template.save(new EntityWithDynamicLabelsAndIdThatNeedsToBeConverted(label)))
389+
.doOnNext(s -> generatedUUID.set(s.getId()))
390+
.as(StepVerifier::create)
391+
.expectNextMatches(expectatations)
392+
.verifyComplete();
393+
394+
template.findById(generatedUUID.get(), EntityWithDynamicLabelsAndIdThatNeedsToBeConverted.class)
395+
.as(StepVerifier::create)
396+
.expectNextMatches(expectatations)
397+
.verifyComplete();
398+
}
375399
}
376400

377401
@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)