fix: Use contextual Cypher-DSL configuration for rendering statements in various Cypher-DSL based query extension.
Fixes #2927. # Conflicts: # src/main/java/org/springframework/data/neo4j/core/ReactiveNeo4jTemplate.java
This commit is contained in:
@@ -136,10 +136,7 @@ public interface FluentFindOperation {
|
||||
* @return new instance of {@link TerminatingFind}.
|
||||
* @throws IllegalArgumentException if statement is {@literal null}.
|
||||
*/
|
||||
default TerminatingFind<T> matching(Statement statement, @Nullable Map<String, Object> parameter) {
|
||||
|
||||
return matching(statement.getCypher(), TemplateSupport.mergeParameters(statement, parameter));
|
||||
}
|
||||
TerminatingFind<T> matching(Statement statement, @Nullable Map<String, Object> parameter);
|
||||
|
||||
/**
|
||||
* Set the filter {@link Statement statement} to be used.
|
||||
|
||||
@@ -19,6 +19,7 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.neo4j.cypherdsl.core.Statement;
|
||||
import org.springframework.data.neo4j.repository.query.QueryFragmentsAndParameters;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -87,7 +88,6 @@ final class FluentOperationSupport implements FluentFindOperation, FluentSaveOpe
|
||||
public TerminatingFind<T> matching(String query, Map<String, Object> parameters) {
|
||||
|
||||
Assert.notNull(query, "Query must not be null");
|
||||
|
||||
return new ExecutableFindSupport<>(template, domainType, returnType, query, parameters);
|
||||
}
|
||||
|
||||
@@ -100,6 +100,12 @@ final class FluentOperationSupport implements FluentFindOperation, FluentSaveOpe
|
||||
return new ExecutableFindSupport<>(template, domainType, returnType, queryFragmentsAndParameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TerminatingFind<T> matching(Statement statement, Map<String, Object> parameter) {
|
||||
|
||||
return matching(template.render(statement), TemplateSupport.mergeParameters(statement, parameter));
|
||||
}
|
||||
|
||||
@Override
|
||||
public T oneValue() {
|
||||
|
||||
|
||||
@@ -1099,6 +1099,10 @@ public final class Neo4jTemplate implements
|
||||
return results;
|
||||
}
|
||||
|
||||
String render(Statement statement) {
|
||||
return renderer.render(statement);
|
||||
}
|
||||
|
||||
final class DefaultExecutableQuery<T> implements ExecutableQuery<T> {
|
||||
|
||||
private final PreparedQuery<T> preparedQuery;
|
||||
|
||||
@@ -126,9 +126,7 @@ public interface ReactiveFluentFindOperation {
|
||||
* @return new instance of {@link TerminatingFind}.
|
||||
* @throws IllegalArgumentException if statement is {@literal null}.
|
||||
*/
|
||||
default TerminatingFind<T> matching(Statement statement, @Nullable Map<String, Object> parameter) {
|
||||
return matching(statement.getCypher(), TemplateSupport.mergeParameters(statement, parameter));
|
||||
}
|
||||
TerminatingFind<T> matching(Statement statement, @Nullable Map<String, Object> parameter);
|
||||
|
||||
/**
|
||||
* Set the filter {@link Statement statement} to be used.
|
||||
|
||||
@@ -21,6 +21,7 @@ import reactor.core.publisher.Mono;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import org.neo4j.cypherdsl.core.Statement;
|
||||
import org.springframework.data.neo4j.repository.query.QueryFragmentsAndParameters;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -101,6 +102,12 @@ final class ReactiveFluentOperationSupport implements ReactiveFluentFindOperatio
|
||||
return new ExecutableFindSupport<>(template, domainType, returnType, queryFragmentsAndParameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TerminatingFind<T> matching(Statement statement, Map<String, Object> parameter) {
|
||||
|
||||
return matching(template.render(statement), TemplateSupport.mergeParameters(statement, parameter));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<T> one() {
|
||||
return doFind(TemplateSupport.FetchType.ONE).single();
|
||||
|
||||
@@ -1172,7 +1172,11 @@ public final class ReactiveNeo4jTemplate implements
|
||||
return new ReactiveFluentOperationSupport(this).save(domainType);
|
||||
}
|
||||
|
||||
static final class DefaultReactiveExecutableQuery<T> implements ExecutableQuery<T> {
|
||||
String render(Statement statement) {
|
||||
return this.renderer.render(statement);
|
||||
}
|
||||
|
||||
final class DefaultReactiveExecutableQuery<T> implements ExecutableQuery<T> {
|
||||
|
||||
private final PreparedQuery<T> preparedQuery;
|
||||
private final ReactiveNeo4jClient.RecordFetchSpec<T> fetchSpec;
|
||||
|
||||
@@ -19,6 +19,7 @@ import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
@@ -44,15 +45,20 @@ import org.springframework.util.Assert;
|
||||
final class CypherdslBasedQuery extends AbstractNeo4jQuery {
|
||||
|
||||
static CypherdslBasedQuery create(Neo4jOperations neo4jOperations, Neo4jMappingContext mappingContext,
|
||||
Neo4jQueryMethod queryMethod, ProjectionFactory projectionFactory) {
|
||||
Neo4jQueryMethod queryMethod, ProjectionFactory projectionFactory,
|
||||
Function<Statement, String> renderer) {
|
||||
|
||||
return new CypherdslBasedQuery(neo4jOperations, mappingContext, queryMethod, Neo4jQueryType.DEFAULT, projectionFactory);
|
||||
return new CypherdslBasedQuery(neo4jOperations, mappingContext, queryMethod, Neo4jQueryType.DEFAULT, projectionFactory, renderer);
|
||||
}
|
||||
|
||||
private final Function<Statement, String> renderer;
|
||||
|
||||
private CypherdslBasedQuery(Neo4jOperations neo4jOperations,
|
||||
Neo4jMappingContext mappingContext,
|
||||
Neo4jQueryMethod queryMethod, Neo4jQueryType queryType, ProjectionFactory projectionFactory) {
|
||||
Neo4jQueryMethod queryMethod, Neo4jQueryType queryType, ProjectionFactory projectionFactory,
|
||||
Function<Statement, String> renderer) {
|
||||
super(neo4jOperations, mappingContext, queryMethod, queryType, projectionFactory);
|
||||
this.renderer = renderer;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -86,7 +92,7 @@ final class CypherdslBasedQuery extends AbstractNeo4jQuery {
|
||||
|
||||
Map<String, Object> boundParameters = statement.getCatalog().getParameters();
|
||||
return PreparedQuery.queryFor(returnedType)
|
||||
.withCypherQuery(statement.getCypher())
|
||||
.withCypherQuery(renderer.apply(statement))
|
||||
.withParameters(boundParameters)
|
||||
.usingMappingFunction(mappingFunction)
|
||||
.build();
|
||||
@@ -98,7 +104,7 @@ final class CypherdslBasedQuery extends AbstractNeo4jQuery {
|
||||
// We verified this above
|
||||
Statement countStatement = (Statement) parameterAccessor.getValues()[1];
|
||||
return Optional.of(PreparedQuery.queryFor(Long.class)
|
||||
.withCypherQuery(countStatement.getCypher())
|
||||
.withCypherQuery(renderer.apply(countStatement))
|
||||
.withParameters(countStatement.getCatalog().getParameters()).build());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ package org.springframework.data.neo4j.repository.query;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.apiguardian.api.API;
|
||||
import org.neo4j.cypherdsl.core.renderer.Configuration;
|
||||
import org.neo4j.cypherdsl.core.renderer.Renderer;
|
||||
import org.springframework.data.neo4j.core.Neo4jOperations;
|
||||
import org.springframework.data.neo4j.core.mapping.Neo4jMappingContext;
|
||||
import org.springframework.data.projection.ProjectionFactory;
|
||||
@@ -40,12 +42,14 @@ public final class Neo4jQueryLookupStrategy implements QueryLookupStrategy {
|
||||
private final Neo4jMappingContext mappingContext;
|
||||
private final Neo4jOperations neo4jOperations;
|
||||
private final QueryMethodEvaluationContextProvider evaluationContextProvider;
|
||||
private final Configuration configuration;
|
||||
|
||||
public Neo4jQueryLookupStrategy(Neo4jOperations neo4jOperations, Neo4jMappingContext mappingContext,
|
||||
QueryMethodEvaluationContextProvider evaluationContextProvider) {
|
||||
QueryMethodEvaluationContextProvider evaluationContextProvider, Configuration configuration) {
|
||||
this.neo4jOperations = neo4jOperations;
|
||||
this.mappingContext = mappingContext;
|
||||
this.evaluationContextProvider = evaluationContextProvider;
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
@@ -65,7 +69,7 @@ public final class Neo4jQueryLookupStrategy implements QueryLookupStrategy {
|
||||
return StringBasedNeo4jQuery.create(neo4jOperations, mappingContext, evaluationContextProvider, queryMethod,
|
||||
factory);
|
||||
} else if (queryMethod.isCypherBasedProjection()) {
|
||||
return CypherdslBasedQuery.create(neo4jOperations, mappingContext, queryMethod, factory);
|
||||
return CypherdslBasedQuery.create(neo4jOperations, mappingContext, queryMethod, factory, Renderer.getRenderer(configuration)::render);
|
||||
} else {
|
||||
return PartTreeNeo4jQuery.create(neo4jOperations, mappingContext, queryMethod, factory);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.data.neo4j.repository.query;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
@@ -42,15 +43,19 @@ import org.springframework.util.Assert;
|
||||
final class ReactiveCypherdslBasedQuery extends AbstractReactiveNeo4jQuery {
|
||||
|
||||
static ReactiveCypherdslBasedQuery create(ReactiveNeo4jOperations neo4jOperations, Neo4jMappingContext mappingContext,
|
||||
Neo4jQueryMethod queryMethod, ProjectionFactory projectionFactory) {
|
||||
Neo4jQueryMethod queryMethod, ProjectionFactory projectionFactory, Function<Statement, String> renderer) {
|
||||
|
||||
return new ReactiveCypherdslBasedQuery(neo4jOperations, mappingContext, queryMethod, Neo4jQueryType.DEFAULT, projectionFactory);
|
||||
return new ReactiveCypherdslBasedQuery(neo4jOperations, mappingContext, queryMethod, Neo4jQueryType.DEFAULT, projectionFactory, renderer);
|
||||
}
|
||||
|
||||
private final Function<Statement, String> renderer;
|
||||
|
||||
private ReactiveCypherdslBasedQuery(ReactiveNeo4jOperations neo4jOperations,
|
||||
Neo4jMappingContext mappingContext,
|
||||
Neo4jQueryMethod queryMethod, Neo4jQueryType queryType, ProjectionFactory projectionFactory) {
|
||||
Neo4jQueryMethod queryMethod, Neo4jQueryType queryType, ProjectionFactory projectionFactory,
|
||||
Function<Statement, String> renderer) {
|
||||
super(neo4jOperations, mappingContext, queryMethod, queryType, projectionFactory);
|
||||
this.renderer = renderer;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -68,7 +73,7 @@ final class ReactiveCypherdslBasedQuery extends AbstractReactiveNeo4jQuery {
|
||||
|
||||
Map<String, Object> boundParameters = statement.getCatalog().getParameters();
|
||||
return PreparedQuery.queryFor(returnedType)
|
||||
.withCypherQuery(statement.getCypher())
|
||||
.withCypherQuery(renderer.apply(statement))
|
||||
.withParameters(boundParameters)
|
||||
.usingMappingFunction(mappingFunction)
|
||||
.build();
|
||||
|
||||
@@ -18,6 +18,8 @@ package org.springframework.data.neo4j.repository.query;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.apiguardian.api.API;
|
||||
import org.neo4j.cypherdsl.core.renderer.Configuration;
|
||||
import org.neo4j.cypherdsl.core.renderer.Renderer;
|
||||
import org.springframework.data.neo4j.core.ReactiveNeo4jOperations;
|
||||
import org.springframework.data.neo4j.core.mapping.Neo4jMappingContext;
|
||||
import org.springframework.data.projection.ProjectionFactory;
|
||||
@@ -40,12 +42,14 @@ public final class ReactiveNeo4jQueryLookupStrategy implements QueryLookupStrate
|
||||
private final ReactiveNeo4jOperations neo4jOperations;
|
||||
private final Neo4jMappingContext mappingContext;
|
||||
private final QueryMethodEvaluationContextProvider evaluationContextProvider;
|
||||
private final Configuration configuration;
|
||||
|
||||
public ReactiveNeo4jQueryLookupStrategy(ReactiveNeo4jOperations neo4jOperations, Neo4jMappingContext mappingContext,
|
||||
QueryMethodEvaluationContextProvider evaluationContextProvider) {
|
||||
QueryMethodEvaluationContextProvider evaluationContextProvider, Configuration configuration) {
|
||||
this.neo4jOperations = neo4jOperations;
|
||||
this.mappingContext = mappingContext;
|
||||
this.evaluationContextProvider = evaluationContextProvider;
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
@@ -65,7 +69,7 @@ public final class ReactiveNeo4jQueryLookupStrategy implements QueryLookupStrate
|
||||
return ReactiveStringBasedNeo4jQuery.create(neo4jOperations, mappingContext, evaluationContextProvider,
|
||||
queryMethod, projectionFactory);
|
||||
} else if (queryMethod.isCypherBasedProjection()) {
|
||||
return ReactiveCypherdslBasedQuery.create(neo4jOperations, mappingContext, queryMethod, projectionFactory);
|
||||
return ReactiveCypherdslBasedQuery.create(neo4jOperations, mappingContext, queryMethod, projectionFactory, Renderer.getRenderer(configuration)::render);
|
||||
} else {
|
||||
return ReactivePartTreeNeo4jQuery.create(neo4jOperations, mappingContext, queryMethod, projectionFactory);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,9 @@ package org.springframework.data.neo4j.repository.support;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.neo4j.cypherdsl.core.renderer.Configuration;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.data.neo4j.core.Neo4jOperations;
|
||||
import org.springframework.data.neo4j.core.mapping.Neo4jMappingContext;
|
||||
import org.springframework.data.neo4j.core.mapping.Neo4jPersistentEntity;
|
||||
@@ -51,6 +54,8 @@ final class Neo4jRepositoryFactory extends RepositoryFactorySupport {
|
||||
|
||||
private final Neo4jMappingContext mappingContext;
|
||||
|
||||
private Configuration cypherDSLConfiguration = Configuration.defaultConfig();
|
||||
|
||||
Neo4jRepositoryFactory(Neo4jOperations neo4jOperations, Neo4jMappingContext mappingContext) {
|
||||
|
||||
this.neo4jOperations = neo4jOperations;
|
||||
@@ -122,6 +127,14 @@ final class Neo4jRepositoryFactory extends RepositoryFactorySupport {
|
||||
return SimpleNeo4jRepository.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
super.setBeanFactory(beanFactory);
|
||||
this.cypherDSLConfiguration = beanFactory
|
||||
.getBeanProvider(Configuration.class)
|
||||
.getIfAvailable(Configuration::defaultConfig);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.core.support.RepositoryFactorySupport#getQueryLookupStrategy(org.springframework.data.repository.query.QueryLookupStrategy.Key, org.springframework.data.repository.query.EvaluationContextProvider)
|
||||
@@ -130,7 +143,7 @@ final class Neo4jRepositoryFactory extends RepositoryFactorySupport {
|
||||
protected Optional<QueryLookupStrategy> getQueryLookupStrategy(Key key,
|
||||
QueryMethodEvaluationContextProvider evaluationContextProvider) {
|
||||
|
||||
return Optional.of(new Neo4jQueryLookupStrategy(neo4jOperations, mappingContext, evaluationContextProvider));
|
||||
return Optional.of(new Neo4jQueryLookupStrategy(neo4jOperations, mappingContext, evaluationContextProvider, cypherDSLConfiguration));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -17,6 +17,7 @@ package org.springframework.data.neo4j.repository.support;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.neo4j.cypherdsl.core.renderer.Configuration;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
@@ -55,6 +56,8 @@ final class ReactiveNeo4jRepositoryFactory extends ReactiveRepositoryFactorySupp
|
||||
|
||||
private final Neo4jMappingContext mappingContext;
|
||||
|
||||
private Configuration cypherDSLConfiguration = Configuration.defaultConfig();
|
||||
|
||||
ReactiveNeo4jRepositoryFactory(ReactiveNeo4jOperations neo4jOperations, Neo4jMappingContext mappingContext) {
|
||||
|
||||
this.neo4jOperations = neo4jOperations;
|
||||
@@ -133,7 +136,7 @@ final class ReactiveNeo4jRepositoryFactory extends ReactiveRepositoryFactorySupp
|
||||
QueryMethodEvaluationContextProvider evaluationContextProvider) {
|
||||
|
||||
return Optional
|
||||
.of(new ReactiveNeo4jQueryLookupStrategy(neo4jOperations, mappingContext, evaluationContextProvider));
|
||||
.of(new ReactiveNeo4jQueryLookupStrategy(neo4jOperations, mappingContext, evaluationContextProvider, cypherDSLConfiguration));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -148,6 +151,10 @@ final class ReactiveNeo4jRepositoryFactory extends ReactiveRepositoryFactorySupp
|
||||
factory.addAdvice(advice);
|
||||
});
|
||||
}
|
||||
|
||||
this.cypherDSLConfiguration = beanFactory
|
||||
.getBeanProvider(Configuration.class)
|
||||
.getIfAvailable(Configuration::defaultConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -41,6 +41,7 @@ abstract class AbstractElementIdTestBase {
|
||||
void setupData(LogbackCapture logbackCapture, @Autowired Driver driver, @Autowired BookmarkCapture bookmarkCapture) {
|
||||
|
||||
logbackCapture.addLogger("org.springframework.data.neo4j.cypher.deprecation", Level.WARN);
|
||||
logbackCapture.addLogger("org.springframework.data.neo4j.cypher", Level.DEBUG);
|
||||
try (Session session = driver.session()) {
|
||||
session.run("MATCH (n) DETACH DELETE n").consume();
|
||||
bookmarkCapture.seedWith(session.lastBookmarks());
|
||||
@@ -78,6 +79,7 @@ abstract class AbstractElementIdTestBase {
|
||||
List<String> formattedMessages = logbackCapture.getFormattedMessages();
|
||||
assertThat(formattedMessages)
|
||||
.noneMatch(s -> s.contains("Neo.ClientNotification.Statement.FeatureDeprecationWarning") ||
|
||||
s.contains("The query used a deprecated function. ('id' is no longer supported)"));
|
||||
s.contains("The query used a deprecated function. ('id' is no longer supported)") ||
|
||||
s.matches("(?s).*toString\\(id\\(.*")); // No deprecations are logged when deprecated function call is nested. Anzeige ist raus.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,13 +20,18 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.jupiter.api.Tag;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.neo4j.cypherdsl.core.Cypher;
|
||||
import org.neo4j.cypherdsl.core.Functions;
|
||||
import org.neo4j.cypherdsl.core.Statement;
|
||||
import org.neo4j.driver.Driver;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.neo4j.core.DatabaseSelectionProvider;
|
||||
import org.springframework.data.neo4j.core.Neo4jTemplate;
|
||||
import org.springframework.data.neo4j.core.transaction.Neo4jBookmarkManager;
|
||||
import org.springframework.data.neo4j.core.transaction.Neo4jTransactionManager;
|
||||
import org.springframework.data.neo4j.repository.Neo4jRepository;
|
||||
@@ -351,6 +356,28 @@ public class ImperativeElementIdIT extends AbstractElementIdTestBase {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Tag("GH-2927")
|
||||
void fluentOpsMustUseCypherDSLConfig(
|
||||
LogbackCapture logbackCapture,
|
||||
@Autowired Driver driver,
|
||||
@Autowired BookmarkCapture bookmarkCapture,
|
||||
@Autowired Neo4jTemplate neo4jTemplate) {
|
||||
|
||||
try (var session = driver.session(bookmarkCapture.createSessionConfig())) {
|
||||
session.run("MERGE (n:" + Thing.THING_LABEL + "{foo: 'bar'})").consume();
|
||||
}
|
||||
|
||||
var thingNode = Cypher.node(Thing.THING_LABEL);
|
||||
var cypherStatement = Statement.builder()
|
||||
.match(thingNode)
|
||||
.where(Functions.elementId(thingNode).eq(Cypher.literalOf("test")))
|
||||
.returning(thingNode)
|
||||
.build();
|
||||
neo4jTemplate.find(Thing.class).matching(cypherStatement).one();
|
||||
assertThatLogMessageDoNotIndicateIDUsage(logbackCapture);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableTransactionManagement
|
||||
@EnableNeo4jRepositories(considerNestedRepositories = true)
|
||||
|
||||
@@ -19,13 +19,18 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.jupiter.api.Tag;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.neo4j.cypherdsl.core.Cypher;
|
||||
import org.neo4j.cypherdsl.core.Functions;
|
||||
import org.neo4j.cypherdsl.core.Statement;
|
||||
import org.neo4j.driver.Driver;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.neo4j.core.ReactiveDatabaseSelectionProvider;
|
||||
import org.springframework.data.neo4j.core.ReactiveNeo4jTemplate;
|
||||
import org.springframework.data.neo4j.core.transaction.Neo4jBookmarkManager;
|
||||
import org.springframework.data.neo4j.core.transaction.ReactiveNeo4jTransactionManager;
|
||||
import org.springframework.data.neo4j.repository.ReactiveNeo4jRepository;
|
||||
@@ -39,6 +44,7 @@ import org.springframework.lang.NonNull;
|
||||
import org.springframework.transaction.ReactiveTransactionManager;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -363,6 +369,29 @@ public class ReactiveElementIdIT extends AbstractElementIdTestBase {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Tag("GH-2927")
|
||||
void fluentOpsMustUseCypherDSLConfig(
|
||||
LogbackCapture logbackCapture,
|
||||
@Autowired Driver driver,
|
||||
@Autowired BookmarkCapture bookmarkCapture,
|
||||
@Autowired ReactiveNeo4jTemplate neo4jTemplate) {
|
||||
|
||||
try (var session = driver.session(bookmarkCapture.createSessionConfig())) {
|
||||
session.run("MERGE (n:" + Thing.THING_LABEL + "{foo: 'bar'})").consume();
|
||||
}
|
||||
|
||||
var thingNode = Cypher.node(Thing.THING_LABEL);
|
||||
var cypherStatement = Statement.builder()
|
||||
.match(thingNode)
|
||||
.where(Functions.elementId(thingNode).eq(Cypher.literalOf("test")))
|
||||
.returning(thingNode)
|
||||
.build();
|
||||
neo4jTemplate.find(Thing.class).matching(cypherStatement).all().as(StepVerifier::create)
|
||||
.verifyComplete();
|
||||
assertThatLogMessageDoNotIndicateIDUsage(logbackCapture);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableTransactionManagement
|
||||
@EnableReactiveNeo4jRepositories(considerNestedRepositories = true)
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2011-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.neo4j.integration.issues.pure_element_id;
|
||||
|
||||
import org.springframework.data.neo4j.core.schema.GeneratedValue;
|
||||
import org.springframework.data.neo4j.core.schema.Id;
|
||||
import org.springframework.data.neo4j.core.schema.Node;
|
||||
|
||||
/**
|
||||
* Just a random annotated entity.
|
||||
*/
|
||||
@Node(primaryLabel = Thing.THING_LABEL)
|
||||
public class Thing {
|
||||
|
||||
public static final String THING_LABEL = "THING";
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
String id;
|
||||
String name;
|
||||
}
|
||||
@@ -45,6 +45,7 @@ import org.junit.jupiter.params.provider.ValueSource;
|
||||
import org.mockito.Answers;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.neo4j.cypherdsl.core.renderer.Configuration;
|
||||
import org.neo4j.driver.Values;
|
||||
import org.neo4j.driver.types.Point;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
@@ -199,7 +200,7 @@ final class RepositoryQueryTest {
|
||||
|
||||
final Neo4jQueryLookupStrategy lookupStrategy = new Neo4jQueryLookupStrategy(neo4jOperations,
|
||||
neo4jMappingContext,
|
||||
QueryMethodEvaluationContextProvider.DEFAULT);
|
||||
QueryMethodEvaluationContextProvider.DEFAULT, Configuration.defaultConfig());
|
||||
|
||||
RepositoryQuery query = lookupStrategy.resolveQuery(queryMethod("findById", Object.class),
|
||||
TEST_REPOSITORY_METADATA, PROJECTION_FACTORY, namedQueries);
|
||||
@@ -210,7 +211,7 @@ final class RepositoryQueryTest {
|
||||
void shouldSelectStringBasedNeo4jQuery() {
|
||||
|
||||
final Neo4jQueryLookupStrategy lookupStrategy = new Neo4jQueryLookupStrategy(neo4jOperations,
|
||||
neo4jMappingContext, QueryMethodEvaluationContextProvider.DEFAULT);
|
||||
neo4jMappingContext, QueryMethodEvaluationContextProvider.DEFAULT, Configuration.defaultConfig());
|
||||
|
||||
RepositoryQuery query = lookupStrategy.resolveQuery(queryMethod("annotatedQueryWithValidTemplate"),
|
||||
TEST_REPOSITORY_METADATA, PROJECTION_FACTORY, namedQueries);
|
||||
@@ -225,7 +226,7 @@ final class RepositoryQueryTest {
|
||||
when(namedQueries.getQuery(namedQueryName)).thenReturn("MATCH (n) RETURN n");
|
||||
|
||||
final Neo4jQueryLookupStrategy lookupStrategy = new Neo4jQueryLookupStrategy(neo4jOperations,
|
||||
neo4jMappingContext, QueryMethodEvaluationContextProvider.DEFAULT);
|
||||
neo4jMappingContext, QueryMethodEvaluationContextProvider.DEFAULT, Configuration.defaultConfig());
|
||||
|
||||
RepositoryQuery query = lookupStrategy
|
||||
.resolveQuery(queryMethod("findAllByANamedQuery"), TEST_REPOSITORY_METADATA,
|
||||
|
||||
Reference in New Issue
Block a user