Skip to content

Commit ade01cb

Browse files
feat: Use label expressions for dynamic labels when available.
This uses the new features of Cypher-DSL to express lists of labels during - match - creation - modification (setting / removing) labels of entities with dynamic labels. On older Neo4j lists of labels will still be expressed as static lists, on Neo4j 5.26 and later, they will use expressions. This change has been tested on - latest 4.4 - latest 5.26 - latest 2025.x It turned out that in the case of 4.4 there are still edge cases in which elementId is called and tests will fail. Those will be addressed in as separate commit. Also, several tests for vector properties and indexes have now been disabled on early databases, so that the build succeeds. Using the correct Cypher DSL dialect is paramount for this feature to work proper, some integration tests had not been configured properly. This closes #3043. Signed-off-by: Michael Simons <michael@simons.ac>
1 parent 52bb9ed commit ade01cb

25 files changed

+261
-52
lines changed

ci/test.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ mkdir -p /tmp/jenkins-home
2222

2323
export JENKINS_USER=${JENKINS_USER_NAME}
2424
export SDN_FORCE_REUSE_OF_CONTAINERS=true
25-
export SDN_NEO4J_VERSION=5.26.2
25+
export SDN_NEO4J_VERSION=5.26.12
2626

2727
MAVEN_OPTS="-Duser.name=${JENKINS_USER} -Duser.home=/tmp/jenkins-home -Dscan=false" \
2828
./mvnw -s settings.xml -P${PROFILE} clean dependency:list verify -Dsort -U -B -Dmaven.repo.local=/tmp/jenkins-home/.m2/spring-data-neo4j -Ddevelocity.storage.directory=/tmp/jenkins-home/.develocity-root

pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@
7777
<blockhound.version>1.0.8.RELEASE</blockhound.version>
7878
<checkstyle.skip>${skipTests}</checkstyle.skip>
7979
<checkstyle.version>10.20.1</checkstyle.version>
80-
<cypher-dsl.version>2025.0.0</cypher-dsl.version>
80+
<cypher-dsl.version>2025.0.2</cypher-dsl.version>
8181
<dist.id>spring-data-neo4j</dist.id>
8282
<dist.key>SDNEO4J</dist.key>
8383
<flatten-maven-plugin.version>1.7.0</flatten-maven-plugin.version>
@@ -99,7 +99,7 @@
9999
<maven.compiler.release>${java.version}</maven.compiler.release>
100100
<neo4j-java-driver.version>5.28.9</neo4j-java-driver.version>
101101
<neo4j-migrations.version>2.17.3</neo4j-migrations.version>
102-
<neo4j.version>4.4.41</neo4j.version>
102+
<neo4j.version>5.26.12</neo4j.version>
103103
<objenesis.version>3.0.1</objenesis.version>
104104
<org.osgi.core.version>6.0.0</org.osgi.core.version>
105105
<project.build.docs>${project.build.directory}/docs</project.build.docs>

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,14 @@ final class DynamicLabels implements UnaryOperator<OngoingMatchAndUpdate> {
5454

5555
@Override
5656
public OngoingMatchAndUpdate apply(OngoingMatchAndUpdate ongoingMatchAndUpdate) {
57-
5857
OngoingMatchAndUpdate decoratedMatchAndUpdate = ongoingMatchAndUpdate;
5958
if (!this.oldLabels.isEmpty()) {
6059
decoratedMatchAndUpdate = decoratedMatchAndUpdate.remove(this.rootNode,
61-
this.oldLabels.toArray(new String[0]));
60+
Cypher.allLabels(Cypher.anonParameter(this.oldLabels)));
6261
}
6362
if (!this.newLabels.isEmpty()) {
64-
decoratedMatchAndUpdate = decoratedMatchAndUpdate.set(this.rootNode, this.newLabels.toArray(new String[0]));
63+
decoratedMatchAndUpdate = decoratedMatchAndUpdate.set(this.rootNode,
64+
Cypher.allLabels(Cypher.anonParameter(this.newLabels)));
6565
}
6666
return decoratedMatchAndUpdate;
6767
}

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

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -468,11 +468,12 @@ private <T> T saveImpl(T instance, @Nullable Collection<PropertyFilter.Projected
468468
TemplateSupport.FilteredBinderFunction<T> binderFunction = TemplateSupport.createAndApplyPropertyFilter(
469469
includedProperties, entityMetaData,
470470
this.neo4jMappingContext.getRequiredBinderFunctionFor((Class<T>) entityToBeSaved.getClass()));
471-
Optional<Entity> newOrUpdatedNode = this.neo4jClient
472-
.query(() -> this.renderer.render(this.cypherGenerator.prepareSaveOf(entityMetaData, dynamicLabels,
473-
TemplateSupport.rendererRendersElementId(this.renderer))))
471+
var statement = this.cypherGenerator.prepareSaveOf(entityMetaData, dynamicLabels,
472+
TemplateSupport.rendererRendersElementId(this.renderer));
473+
Optional<Entity> newOrUpdatedNode = this.neo4jClient.query(() -> this.renderer.render(statement))
474474
.bind(entityToBeSaved)
475475
.with(binderFunction)
476+
.bindAll(statement.getCatalog().getParameters())
476477
.fetchAs(Entity.class)
477478
.one();
478479

@@ -516,14 +517,16 @@ private <T> DynamicLabels determineDynamicLabels(T entityToBeSaved, Neo4jPersist
516517

517518
PersistentPropertyAccessor<T> propertyAccessor = entityMetaData.getPropertyAccessor(entityToBeSaved);
518519
Neo4jPersistentProperty idProperty = entityMetaData.getRequiredIdProperty();
520+
var statementReturningDynamicLabels = this.cypherGenerator
521+
.createStatementReturningDynamicLabels(entityMetaData);
519522
Neo4jClient.RunnableSpec runnableQuery = this.neo4jClient
520-
.query(() -> this.renderer
521-
.render(this.cypherGenerator.createStatementReturningDynamicLabels(entityMetaData)))
523+
.query(() -> this.renderer.render(statementReturningDynamicLabels))
522524
.bind(TemplateSupport.convertIdValues(this.neo4jMappingContext, idProperty,
523525
propertyAccessor.getProperty(idProperty)))
524526
.to(Constants.NAME_OF_ID)
525527
.bind(entityMetaData.getStaticLabels())
526-
.to(Constants.NAME_OF_STATIC_LABELS_PARAM);
528+
.to(Constants.NAME_OF_STATIC_LABELS_PARAM)
529+
.bindAll(statementReturningDynamicLabels.getCatalog().getParameters());
527530

528531
if (entityMetaData.hasVersionProperty()) {
529532
runnableQuery = runnableQuery
@@ -620,10 +623,11 @@ class Tuple3<T> {
620623
.map(h -> h.modifiedInstance)
621624
.map(binderFunction)
622625
.collect(Collectors.toList());
623-
Map<Value, String> idToInternalIdMapping = this.neo4jClient
624-
.query(() -> this.renderer.render(this.cypherGenerator.prepareSaveOfMultipleInstancesOf(entityMetaData)))
626+
var statement = this.cypherGenerator.prepareSaveOfMultipleInstancesOf(entityMetaData);
627+
Map<Value, String> idToInternalIdMapping = this.neo4jClient.query(() -> this.renderer.render(statement))
625628
.bind(entityList)
626629
.to(Constants.NAME_OF_ENTITY_LIST_PARAM)
630+
.bindAll(statement.getCatalog().getParameters())
627631
.fetchAs(Map.Entry.class)
628632
.mappedBy((t, r) -> new AbstractMap.SimpleEntry<>(r.get(Constants.NAME_OF_ID),
629633
TemplateSupport.convertIdOrElementIdToString(r.get(Constants.NAME_OF_ELEMENT_ID))))
@@ -726,6 +730,7 @@ public <T> void deleteById(Object id, Class<T> domainType) {
726730
.bind(TemplateSupport.convertIdValues(this.neo4jMappingContext, entityMetaData.getRequiredIdProperty(),
727731
id))
728732
.to(nameOfParameter)
733+
.bindAll(statement.getCatalog().getParameters())
729734
.run();
730735

731736
log.debug(() -> String.format("Deleted %d nodes and %d relationships.", summary.counters().nodesDeleted(),
@@ -786,6 +791,7 @@ public <T> void deleteAllById(Iterable<?> ids, Class<T> domainType) {
786791
.bind(TemplateSupport.convertIdValues(this.neo4jMappingContext, entityMetaData.getRequiredIdProperty(),
787792
ids))
788793
.to(nameOfParameter)
794+
.bindAll(statement.getCatalog().getParameters())
789795
.run();
790796

791797
log.debug(() -> String.format("Deleted %d nodes and %d relationships.", summary.counters().nodesDeleted(),
@@ -944,6 +950,7 @@ private <T> T processNestedRelations(Neo4jPersistentEntity<?> sourceEntity,
944950
.to(Constants.FROM_ID_PARAMETER_NAME) //
945951
.bind(knownRelationshipsIds) //
946952
.to(Constants.NAME_OF_KNOWN_RELATIONSHIPS_PARAM) //
953+
.bindAll(relationshipRemoveQuery.getCatalog().getParameters())
947954
.run();
948955
}
949956

@@ -1132,6 +1139,7 @@ else if (relationshipDescription.hasRelationshipProperties() && fromId != null)
11321139
plainRelationshipRows);
11331140
this.neo4jClient.query(this.renderer.render(statementHolder.getStatement()))
11341141
.bindAll(statementHolder.getProperties())
1142+
.bindAll(statementHolder.getStatement().getCatalog().getParameters())
11351143
.run();
11361144
}
11371145
else if (relationshipDescription.hasRelationshipProperties()) {
@@ -1145,6 +1153,7 @@ else if (relationshipDescription.hasRelationshipProperties()) {
11451153

11461154
this.neo4jClient.query(this.renderer.render(statementHolder.getStatement()))
11471155
.bindAll(statementHolder.getProperties())
1156+
.bindAll(statementHolder.getStatement().getCatalog().getParameters())
11481157
.run();
11491158
}
11501159
if (!(newRelationshipPropertiesToStore.isEmpty() || idProperty == null)) {
@@ -1155,6 +1164,7 @@ else if (relationshipDescription.hasRelationshipProperties()) {
11551164
List<Object> all = new ArrayList<>(
11561165
this.neo4jClient.query(this.renderer.render(statementHolder.getStatement()))
11571166
.bindAll(statementHolder.getProperties())
1167+
.bindAll(statementHolder.getStatement().getCatalog().getParameters())
11581168
.fetchAs(Object.class)
11591169
.mappedBy((t, r) -> IdentitySupport.mapperForRelatedIdValues(idProperty).apply(r))
11601170
.all());
@@ -1187,6 +1197,7 @@ private Optional<Object> getRelationshipId(Statement statement, @Nullable Neo4jP
11871197
.to(Constants.FROM_ID_PARAMETER_NAME) //
11881198
.bind(toId) //
11891199
.to(Constants.TO_ID_PARAMETER_NAME) //
1200+
.bindAll(statement.getCatalog().getParameters())
11901201
.fetchAs(Object.class)
11911202
.mappedBy((t, r) -> IdentitySupport.mapperForRelatedIdValues(idProperty).apply(r))
11921203
.one();
@@ -1255,11 +1266,12 @@ private Entity saveRelatedNode(Object entity, NodeDescription<?> targetNodeDescr
12551266
}
12561267
return tree;
12571268
});
1258-
Optional<Entity> optionalSavedNode = this.neo4jClient
1259-
.query(() -> this.renderer.render(this.cypherGenerator.prepareSaveOf(targetNodeDescription, dynamicLabels,
1260-
TemplateSupport.rendererRendersElementId(this.renderer))))
1269+
var statement = this.cypherGenerator.prepareSaveOf(targetNodeDescription, dynamicLabels,
1270+
TemplateSupport.rendererRendersElementId(this.renderer));
1271+
Optional<Entity> optionalSavedNode = this.neo4jClient.query(() -> this.renderer.render(statement))
12611272
.bind(entity)
12621273
.with(binderFunction)
1274+
.bindAll(statement.getCatalog().getParameters())
12631275
.fetchAs(Entity.class)
12641276
.one();
12651277

@@ -1605,6 +1617,7 @@ private void iterateNextLevel(Collection<String> nodeIds, RelationshipDescriptio
16051617
Neo4jTemplate.this.neo4jClient.query(Neo4jTemplate.this.renderer.render(statement))
16061618
.bindAll(Collections.singletonMap(Constants.NAME_OF_IDS,
16071619
TemplateSupport.convertToLongIdOrStringElementId(nodeIds)))
1620+
.bindAll(statement.getCatalog().getParameters())
16081621
.fetch()
16091622
.one()
16101623
.ifPresent(

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

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -508,11 +508,11 @@ private <T> Mono<T> saveImpl(T instance, @Nullable Collection<PropertyFilter.Pro
508508
this.neo4jMappingContext.getRequiredBinderFunctionFor((Class<T>) entityToBeSaved.getClass()));
509509

510510
boolean canUseElementId = TemplateSupport.rendererRendersElementId(this.renderer);
511-
Mono<Entity> idMono = this.neo4jClient
512-
.query(() -> this.renderer
513-
.render(this.cypherGenerator.prepareSaveOf(entityMetaData, dynamicLabels, canUseElementId)))
511+
var statement = this.cypherGenerator.prepareSaveOf(entityMetaData, dynamicLabels, canUseElementId);
512+
Mono<Entity> idMono = this.neo4jClient.query(() -> this.renderer.render(statement))
514513
.bind(entityToBeSaved)
515514
.with(binderFunction)
515+
.bindAll(statement.getCatalog().getParameters())
516516
.fetchAs(Entity.class)
517517
.one()
518518
.switchIfEmpty(Mono.defer(() -> {
@@ -545,14 +545,16 @@ private <T> Mono<Tuple2<T, DynamicLabels>> determineDynamicLabels(T entityToBeSa
545545

546546
PersistentPropertyAccessor<?> propertyAccessor = entityMetaData.getPropertyAccessor(entityToBeSaved);
547547
Neo4jPersistentProperty idProperty = entityMetaData.getRequiredIdProperty();
548+
var statementReturningDynamicLabels = this.cypherGenerator
549+
.createStatementReturningDynamicLabels(entityMetaData);
548550
ReactiveNeo4jClient.RunnableSpec runnableQuery = this.neo4jClient
549-
.query(() -> this.renderer
550-
.render(this.cypherGenerator.createStatementReturningDynamicLabels(entityMetaData)))
551+
.query(() -> this.renderer.render(statementReturningDynamicLabels))
551552
.bind(TemplateSupport.convertIdValues(this.neo4jMappingContext, idProperty,
552553
propertyAccessor.getProperty(idProperty)))
553554
.to(Constants.NAME_OF_ID)
554555
.bind(entityMetaData.getStaticLabels())
555-
.to(Constants.NAME_OF_STATIC_LABELS_PARAM);
556+
.to(Constants.NAME_OF_STATIC_LABELS_PARAM)
557+
.bindAll(statementReturningDynamicLabels.getCatalog().getParameters());
556558

557559
if (entityMetaData.hasVersionProperty()) {
558560
runnableQuery = runnableQuery
@@ -683,19 +685,18 @@ private <T> Flux<T> saveAllImpl(Iterable<T> instances,
683685
.map(Tuple3::getT3) // extract PotentiallyModified
684686
.map(binderFunction)
685687
.collect(Collectors.toList());
686-
return this.neo4jClient
687-
.query(() -> this.renderer
688-
.render(this.cypherGenerator.prepareSaveOfMultipleInstancesOf(entityMetaData)))
688+
var statement = this.cypherGenerator.prepareSaveOfMultipleInstancesOf(entityMetaData);
689+
return this.neo4jClient.query(() -> this.renderer.render(statement))
689690
.bind(boundedEntityList)
690691
.to(Constants.NAME_OF_ENTITY_LIST_PARAM)
692+
.bindAll(statement.getCatalog().getParameters())
691693
.fetchAs(Tuple2.class)
692694
.mappedBy((t, r) -> Tuples.of(r.get(Constants.NAME_OF_ID),
693695
TemplateSupport.convertIdOrElementIdToString(r.get(Constants.NAME_OF_ELEMENT_ID))))
694696
.all()
695697
.collectMap(m -> (Value) m.getT1(), m -> (String) m.getT2());
696698
}).flatMapMany(idToInternalIdMapping -> Flux.fromIterable(entitiesToBeSaved).concatMap(t -> {
697699
PersistentPropertyAccessor<T> propertyAccessor = entityMetaData.getPropertyAccessor(t.getT3());
698-
Neo4jPersistentProperty idProperty = entityMetaData.getRequiredIdProperty();
699700
return processRelations(entityMetaData, propertyAccessor, t.getT2(), ctx.get("stateMachine"),
700701
ctx.get("knownRelIds"),
701702
TemplateSupport
@@ -722,6 +723,7 @@ public <T> Mono<Void> deleteAllById(Iterable<?> ids, Class<T> domainType) {
722723
.bind(TemplateSupport.convertIdValues(this.neo4jMappingContext, entityMetaData.getRequiredIdProperty(),
723724
ids))
724725
.to(nameOfParameter)
726+
.bindAll(statement.getCatalog().getParameters())
725727
.run()
726728
.then()));
727729
}
@@ -739,6 +741,7 @@ public <T> Mono<Void> deleteById(Object id, Class<T> domainType) {
739741
return execute(Mono.defer(() -> this.neo4jClient.query(() -> this.renderer.render(statement))
740742
.bind(TemplateSupport.convertIdValues(this.neo4jMappingContext, entityMetaData.getRequiredIdProperty(), id))
741743
.to(nameOfParameter)
744+
.bindAll(statement.getCatalog().getParameters())
742745
.run()
743746
.then()));
744747
}
@@ -1089,6 +1092,7 @@ private <T> Mono<T> processNestedRelations(Neo4jPersistentEntity<?> sourceEntity
10891092
.to(Constants.FROM_ID_PARAMETER_NAME) //
10901093
.bind(knownRelationshipsIds) //
10911094
.to(Constants.NAME_OF_KNOWN_RELATIONSHIPS_PARAM) //
1095+
.bindAll(relationshipRemoveQuery.getCatalog().getParameters())
10921096
.run()
10931097
.checkpoint("delete relationships")
10941098
.then());
@@ -1227,6 +1231,7 @@ private <T> Mono<T> processNestedRelations(Neo4jPersistentEntity<?> sourceEntity
12271231
.bind(idValue) //
12281232
.to(Constants.NAME_OF_KNOWN_RELATIONSHIP_PARAM) //
12291233
.bindAll(statementHolder.getProperties())
1234+
.bindAll(statementHolder.getStatement().getCatalog().getParameters())
12301235
.fetchAs(Object.class)
12311236
.mappedBy((t, r) -> IdentitySupport.mapperForRelatedIdValues(idProperty).apply(r))
12321237
.one()
@@ -1298,6 +1303,7 @@ private Mono<Object> getRelationshipId(Statement statement, @Nullable Neo4jPersi
12981303
.to(Constants.FROM_ID_PARAMETER_NAME) //
12991304
.bind(toId) //
13001305
.to(Constants.TO_ID_PARAMETER_NAME) //
1306+
.bindAll(statement.getCatalog().getParameters())
13011307
.fetchAs(Object.class)
13021308
.mappedBy((t, r) -> IdentitySupport.mapperForRelatedIdValues(idProperty).apply(r))
13031309
.one();
@@ -1358,11 +1364,12 @@ private Mono<Entity> saveRelatedNode(Object relatedNode, Neo4jPersistentEntity<?
13581364
}
13591365
return tree;
13601366
});
1361-
return this.neo4jClient
1362-
.query(() -> this.renderer.render(this.cypherGenerator.prepareSaveOf(targetNodeDescription,
1363-
dynamicLabels, TemplateSupport.rendererRendersElementId(this.renderer))))
1367+
var statement = this.cypherGenerator.prepareSaveOf(targetNodeDescription, dynamicLabels,
1368+
TemplateSupport.rendererRendersElementId(this.renderer));
1369+
return this.neo4jClient.query(() -> this.renderer.render(statement))
13641370
.bind(entity)
13651371
.with(binderFunction)
1372+
.bindAll(statement.getCatalog().getParameters())
13661373
.fetchAs(Entity.class)
13671374
.one();
13681375
}).switchIfEmpty(Mono.defer(() -> {

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@
6565
import static org.neo4j.cypherdsl.core.Cypher.listBasedOn;
6666
import static org.neo4j.cypherdsl.core.Cypher.literalOf;
6767
import static org.neo4j.cypherdsl.core.Cypher.match;
68-
import static org.neo4j.cypherdsl.core.Cypher.node;
6968
import static org.neo4j.cypherdsl.core.Cypher.optionalMatch;
7069
import static org.neo4j.cypherdsl.core.Cypher.parameter;
7170

@@ -166,6 +165,14 @@ private static Function<Relationship, Expression> getRelationshipIdFunction(
166165
return result;
167166
}
168167

168+
private static Node node(String primaryLabel, List<String> additionalLabels) {
169+
var labels = Cypher.exactlyLabel(primaryLabel);
170+
if (!additionalLabels.isEmpty()) {
171+
labels = labels.conjunctionWith(Cypher.allLabels(Cypher.anonParameter(additionalLabels)));
172+
}
173+
return Cypher.node(labels);
174+
}
175+
169176
private static Condition conditionOrNoCondition(@Nullable Condition condition) {
170177
return (condition != null) ? condition : Cypher.noCondition();
171178
}

src/test/java/org/springframework/data/neo4j/core/mapping/CypherGeneratorTests.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,15 @@
2121
import java.util.regex.Pattern;
2222
import java.util.stream.Stream;
2323

24+
import org.junit.jupiter.api.BeforeAll;
2425
import org.junit.jupiter.api.Test;
2526
import org.junit.jupiter.params.ParameterizedTest;
2627
import org.junit.jupiter.params.provider.Arguments;
2728
import org.junit.jupiter.params.provider.CsvSource;
2829
import org.junit.jupiter.params.provider.MethodSource;
2930
import org.mockito.Mockito;
3031
import org.neo4j.cypherdsl.core.Cypher;
32+
import org.neo4j.cypherdsl.core.FunctionInvocation;
3133
import org.neo4j.cypherdsl.core.Statement;
3234
import org.neo4j.cypherdsl.core.renderer.Configuration;
3335
import org.neo4j.cypherdsl.core.renderer.Dialect;
@@ -57,6 +59,12 @@ private static Stream<Arguments> pageables() {
5759
Arguments.of(Sort.by("n.a").ascending(), Optional.of("ORDER BY n.a ASC")));
5860
}
5961

62+
@BeforeAll
63+
static void fixTheAbusOfASingleton() {
64+
CypherGenerator.INSTANCE
65+
.setElementIdOrIdFunction(n -> FunctionInvocation.create(() -> "elementId", n.getRequiredSymbolicName()));
66+
}
67+
6068
@Test
6169
void shouldCreateRelationshipCreationQueryWithLabelIfPresent() {
6270
Neo4jPersistentEntity<?> persistentEntity = new Neo4jMappingContext().getPersistentEntity(Entity1.class);

src/test/java/org/springframework/data/neo4j/integration/cascading/AbstractCascadingTestBase.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,16 @@
2020
import java.util.Map;
2121

2222
import org.junit.jupiter.api.BeforeAll;
23+
import org.junit.jupiter.api.Tag;
2324
import org.neo4j.driver.Driver;
2425
import org.neo4j.driver.types.TypeSystem;
2526

2627
import org.springframework.beans.factory.annotation.Autowired;
28+
import org.springframework.data.neo4j.test.Neo4jExtension;
2729

2830
import static org.assertj.core.api.Assertions.assertThat;
2931

32+
@Tag(Neo4jExtension.NEEDS_VERSION_SUPPORTING_ELEMENT_ID)
3033
abstract class AbstractCascadingTestBase {
3134

3235
static Map<Class<? extends Parent>, String> EXISTING_IDS = new HashMap<>();

src/test/java/org/springframework/data/neo4j/integration/conversion_imperative/TypeConversionIT.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import org.junit.jupiter.api.DynamicContainer;
3737
import org.junit.jupiter.api.DynamicNode;
3838
import org.junit.jupiter.api.DynamicTest;
39+
import org.junit.jupiter.api.Tag;
3940
import org.junit.jupiter.api.Test;
4041
import org.junit.jupiter.api.TestFactory;
4142
import org.neo4j.driver.Driver;
@@ -68,6 +69,7 @@
6869
import org.springframework.data.neo4j.repository.Neo4jRepository;
6970
import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories;
7071
import org.springframework.data.neo4j.test.BookmarkCapture;
72+
import org.springframework.data.neo4j.test.Neo4jExtension;
7173
import org.springframework.data.neo4j.test.Neo4jImperativeTestConfiguration;
7274
import org.springframework.data.neo4j.test.Neo4jIntegrationTest;
7375
import org.springframework.test.util.ReflectionTestUtils;
@@ -78,10 +80,13 @@
7880
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
7981

8082
/**
83+
* Tag due to the requirements on db.create.setNodeVectorProperty
84+
*
8185
* @author Michael J. Simons
8286
* @author Dennis Crissman
8387
*/
8488
@Neo4jIntegrationTest
89+
@Tag(Neo4jExtension.NEEDS_VECTOR_INDEX)
8590
class TypeConversionIT extends Neo4jConversionsITBase {
8691

8792
private final CypherTypesRepository cypherTypesRepository;

0 commit comments

Comments
 (0)