To begin with, the task appeared to generate cypher requests for data classes based on the annotations @NodeEntity
, @RelationshipEntity
and @Relationship
and additional parameters. A query generator was written, but the query string was calculated in runtime and we could not use it as a parameter of the existing @Query
annotation, so a new @CustomQuery
annotation was added, the processor of which used the written query generator.
Versions of software used:
spring-data-neo4j - 5.0.9.RELEASE
neo4j - 3.4.6
neo4j-ogm - 3.1.4
To add your own mechanism for generating cypher requests for methods of neo4j repositories marked for example, @CustomQuery
you are @CustomQuery
you need to create the CustomNeo4jRepositoryFactory extends Neo4jRepositoryFactory
class CustomNeo4jRepositoryFactory extends Neo4jRepositoryFactory
and redefine the getQueryLookupStrategy
method in it, it should return a new search strategy for query handlers, it should return a new search strategy for query handlers, it should return a new search strategy for CustomGraphQueryLookupStrategy extends GraphQueryLookupStrategy
.
@Override protected Optional<QueryLookupStrategy> getQueryLookupStrategy(QueryLookupStrategy.Key key, EvaluationContextProvider evaluationContextProvider) { return Optional.of(new CustomGraphQueryLookupStrategy(session)); }
You also need to extend the standard Neo4jRepositoryFactoryBean
class Neo4jRepositoryFactoryBean
new CustomNeo4jRepositoryFactoryBean
class and override the createRepositoryFactory
method. It should return a copy of the new repository factory:
@Override protected RepositoryFactorySupport createRepositoryFactory(Session session) { return new CustomNeo4jRepositoryFactory(session); }
In order for Spring Data Neo4j to understand which repository factory bin to use, it must be explicitly indicated in the @EnableNeo4jRepositories
annotation in the configuration:
@EnableNeo4jRepositories(..., repositoryFactoryBeanClass = CustomNeo4jRepositoryFactoryBean.class)
An additional CustomQuery
query query has been CustomQuery
. If the repository method is marked with this annotation, the CustomGraphQueryLookupStrategy
in the override method resolveQuery
will return the object of our query CustomGraphRepositoryQuery extends GraphRepositoryQuery
:
public RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, ProjectionFactory factory, NamedQueries namedQueries) { if (method.isAnnotationPresent(CustomQuery.class)) { GraphQueryMethod queryMethod = new GraphQueryMethod(method, metadata, factory); return new CustomGraphRepositoryQuery(queryMethod, session, method.getAnnotation(CustomQuery.class)); } else { return super.resolveQuery(method, metadata, factory, namedQueries); } }
CustomGraphRepositoryQuery
implements a getQuery
method that returns a Query
object, its constructor accepts a cypher query that was built in CustomGraphRepositoryQuery
based on CustomQuery
annotation CustomQuery
and a Method
object marked with such annotation:
@Override protected Query getQuery(Object[] parameters) { return new Query(query, resolveParams(parameters)); }
The resolveParametres(Object[])
method and resolveParametres(Object[])
used by it are private in GraphRepositoryQuery
, so they were simply copied to CustomGraphRepositoryQuery
(you can use reflection, this will not affect performance, because query generation occurs before runtime).
Thus, you can declare your mechanism for generating cypher-requests, if necessary.
The following articles will describe the query generator itself, its parameters, the mechanism of operation, problems encountered and their solution.
Source: https://habr.com/ru/post/434902/