diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/GraphQueryLookupStrategy.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/GraphQueryLookupStrategy.java index 5e16a1e03..71e7797cf 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/GraphQueryLookupStrategy.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/GraphQueryLookupStrategy.java @@ -28,32 +28,34 @@ import org.springframework.data.repository.query.RepositoryQuery; * @author Luanne Misquitta * @author Oliver Gierke * @author Nicolas Mervaillie + * @author Gerrit Meier */ public class GraphQueryLookupStrategy implements QueryLookupStrategy { - private final Session session; + private final Session session; - public GraphQueryLookupStrategy(Session session) { - this.session = session; - } - - /* - * (non-Javadoc) - * @see org.springframework.data.repository.query.QueryLookupStrategy#resolveQuery(java.lang.reflect.Method, org.springframework.data.repository.core.RepositoryMetadata, org.springframework.data.projection.ProjectionFactory, org.springframework.data.repository.core.NamedQueries) - */ - @Override - public RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, ProjectionFactory factory, - NamedQueries namedQueries) { + public GraphQueryLookupStrategy(Session session) { + this.session = session; + } - GraphQueryMethod queryMethod = new GraphQueryMethod(method, metadata, factory); - String namedQueryName = queryMethod.getNamedQueryName(); + /* + * (non-Javadoc) + * @see org.springframework.data.repository.query.QueryLookupStrategy#resolveQuery(java.lang.reflect.Method, org.springframework.data.repository.core.RepositoryMetadata, org.springframework.data.projection.ProjectionFactory, org.springframework.data.repository.core.NamedQueries) + */ + @Override + public RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, ProjectionFactory factory, + NamedQueries namedQueries) { - if (namedQueries.hasQuery(namedQueryName)) { - throw new UnsupportedOperationException("Named queries are not supported for now."); - } else if (queryMethod.hasAnnotatedQuery()) { - return new GraphRepositoryQuery(queryMethod, session); - } else { - return new DerivedGraphRepositoryQuery(queryMethod, session); - } - } + GraphQueryMethod queryMethod = new GraphQueryMethod(method, metadata, factory); + String namedQueryName = queryMethod.getNamedQueryName(); + + if (namedQueries.hasQuery(namedQueryName)) { + String cypherQuery = namedQueries.getQuery(namedQueryName); + return new NamedGraphRepositoryQuery(queryMethod, session, cypherQuery); + } else if (queryMethod.hasAnnotatedQuery()) { + return new GraphRepositoryQuery(queryMethod, session); + } else { + return new DerivedGraphRepositoryQuery(queryMethod, session); + } + } } diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/GraphRepositoryQuery.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/GraphRepositoryQuery.java index 1ff68d45b..2864eb8c6 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/GraphRepositoryQuery.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/GraphRepositoryQuery.java @@ -80,20 +80,11 @@ public class GraphRepositoryQuery extends AbstractGraphRepositoryQuery { ? result : processor.processResult(result, new CustomResultConverter(getMetaData(), processor.getReturnedType().getReturnedType())); } - // just an horrible trick to get the metadata from OGM - private MetaData getMetaData() { - return session.doInTransaction((requestHandler, transaction, metaData) -> metaData); - } - protected Query getQuery(Object[] parameters) { return new Query(getQueryString(), graphQueryMethod.getCountQueryString(), resolveParams(parameters)); } - private String getQueryString() { - return getQueryMethod().getQuery(); - } - - private Map resolveParams(Object[] parameters) { + Map resolveParams(Object[] parameters) { Map params = new HashMap<>(); Parameters methodParameters = graphQueryMethod.getParameters(); @@ -111,6 +102,15 @@ public class GraphRepositoryQuery extends AbstractGraphRepositoryQuery { return params; } + // just an horrible trick to get the metadata from OGM + private MetaData getMetaData() { + return session.doInTransaction((requestHandler, transaction, metaData) -> metaData); + } + + private String getQueryString() { + return getQueryMethod().getQuery(); + } + private Object getParameterValue(Object parameter) { //The parameter might be an entity, try to resolve its id diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/NamedGraphRepositoryQuery.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/NamedGraphRepositoryQuery.java new file mode 100644 index 000000000..b853a7bb7 --- /dev/null +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/NamedGraphRepositoryQuery.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) [2011-2017] "Pivotal Software, Inc." / "Neo Technology" / "Graph Aware Ltd." + * + * This product is licensed to you under the Apache License, Version 2.0 (the "License"). + * You may not use this product except in compliance with the License. + * + * This product may include a number of subcomponents with + * separate copyright notices and license terms. Your use of the source + * code for these subcomponents is subject to the terms and + * conditions of the subcomponent's license, as noted in the LICENSE file. + * + */ + +package org.springframework.data.neo4j.repository.query; + +import org.neo4j.ogm.session.Session; + +/** + * Specialisation of {@link GraphRepositoryQuery} that creates queries from named queries defined in + * {@code META-INFO/neo4j-named-queries.properties}. + * + * @author Gerrit Meier + */ +public class NamedGraphRepositoryQuery extends GraphRepositoryQuery { + + private final String cypherQuery; + + NamedGraphRepositoryQuery(GraphQueryMethod graphQueryMethod, Session session, String cypherQuery) { + super(graphQueryMethod, session); + this.cypherQuery = cypherQuery; + } + + @Override + protected Query getQuery(Object[] parameters) { + return new Query(cypherQuery, resolveParams(parameters)); + } + +} diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/namedquery/NamedQueryTests.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/namedquery/NamedQueryTests.java new file mode 100644 index 000000000..00acdaa65 --- /dev/null +++ b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/namedquery/NamedQueryTests.java @@ -0,0 +1,90 @@ +package org.springframework.data.neo4j.namedquery; + +import static org.junit.Assert.*; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.neo4j.ogm.config.Configuration; +import org.neo4j.ogm.session.SessionFactory; +import org.neo4j.ogm.testutil.MultiDriverTestClass; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.data.neo4j.namedquery.domain.SampleEntityForNamedQuery; +import org.springframework.data.neo4j.namedquery.repo.SampleEntityForNamedQueryRepository; +import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories; +import org.springframework.data.neo4j.transaction.Neo4jTransactionManager; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; +import org.springframework.transaction.annotation.Transactional; + +@ContextConfiguration(classes = { NamedQueryTests.NamedQueryContext.class }) +@RunWith(SpringJUnit4ClassRunner.class) +@Transactional +public class NamedQueryTests extends MultiDriverTestClass { + + private static final String SAMPLE_ENTITY_NAME = "test"; + + @Autowired private SampleEntityForNamedQueryRepository repository; + + @Test + public void findElementByQueryAnnotation() { + createAndSaveSampleEntity(); + + SampleEntityForNamedQuery titleEntity = repository.getTitleEntity(); + assertNotNull(titleEntity); + } + + @Test + public void findElementByDerivedFunction() { + createAndSaveSampleEntity(); + + SampleEntityForNamedQuery titleEntity = repository.findByName(SAMPLE_ENTITY_NAME); + assertNotNull(titleEntity); + } + + @Test + public void findElementByNamedQuery() { + createAndSaveSampleEntity(); + + SampleEntityForNamedQuery titleEntity = repository.findByQueryWithoutParameter(); + assertNotNull(titleEntity); + } + + @Test + public void findElementByNamedQueryWithParameter() { + createAndSaveSampleEntity(); + + SampleEntityForNamedQuery titleEntity = repository.findByQueryWithParameter(SAMPLE_ENTITY_NAME); + assertNotNull(titleEntity); + } + + private void createAndSaveSampleEntity() { + SampleEntityForNamedQuery entity = new SampleEntityForNamedQuery(); + entity.setName(SAMPLE_ENTITY_NAME); + repository.save(entity); + } + + @org.springframework.context.annotation.Configuration + @ComponentScan({ "org.springframework.data.neo4j.namedquery" }) + @EnableNeo4jRepositories(value = "org.springframework.data.neo4j.namedquery.repo") + @EnableTransactionManagement + static class NamedQueryContext { + + @Bean + public PlatformTransactionManager transactionManager() { + return new Neo4jTransactionManager(sessionFactory()); + } + + @Bean + public SessionFactory sessionFactory() { + Configuration.Builder builder = getBaseConfiguration(); + + Configuration configuration = builder.build(); + + return new SessionFactory(configuration, "org.springframework.data.neo4j.namedquery.domain"); + } + } +} diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/namedquery/domain/SampleEntityForNamedQuery.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/namedquery/domain/SampleEntityForNamedQuery.java new file mode 100644 index 000000000..14c94bab8 --- /dev/null +++ b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/namedquery/domain/SampleEntityForNamedQuery.java @@ -0,0 +1,23 @@ +package org.springframework.data.neo4j.namedquery.domain; + +import org.neo4j.ogm.annotation.NodeEntity; + +@NodeEntity +public class SampleEntityForNamedQuery { + + private Long id; + + private String name; + + public Long getId() { + return id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/namedquery/repo/SampleEntityForNamedQueryRepository.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/namedquery/repo/SampleEntityForNamedQueryRepository.java new file mode 100644 index 000000000..f173f85f7 --- /dev/null +++ b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/namedquery/repo/SampleEntityForNamedQueryRepository.java @@ -0,0 +1,19 @@ +package org.springframework.data.neo4j.namedquery.repo; + +import org.springframework.data.neo4j.annotation.Query; +import org.springframework.data.neo4j.namedquery.domain.SampleEntityForNamedQuery; +import org.springframework.data.neo4j.repository.Neo4jRepository; +import org.springframework.data.repository.query.Param; + +public interface SampleEntityForNamedQueryRepository extends Neo4jRepository { + + @Query("MATCH (e) WHERE e.name='test' RETURN e") + SampleEntityForNamedQuery getTitleEntity(); + + SampleEntityForNamedQuery findByName(String name); + + SampleEntityForNamedQuery findByQueryWithoutParameter(); + + SampleEntityForNamedQuery findByQueryWithParameter(@Param("name") String name); + +} diff --git a/spring-data-neo4j/src/test/resources/META-INF/neo4j-named-queries.properties b/spring-data-neo4j/src/test/resources/META-INF/neo4j-named-queries.properties new file mode 100644 index 000000000..da6e82ac0 --- /dev/null +++ b/spring-data-neo4j/src/test/resources/META-INF/neo4j-named-queries.properties @@ -0,0 +1,2 @@ +SampleEntityForNamedQuery.findByQueryWithoutParameter=MATCH (e) WHERE e.name='test' RETURN e +SampleEntityForNamedQuery.findByQueryWithParameter=MATCH (e) WHERE e.name={name} RETURN e \ No newline at end of file