DATAGRAPH-791 - support named queries in properties files.

Neo4j now works the same as other Spring Data projects by supporting
named queries in `neo4j-named-queries.properties` (default name) files.

(cherry picked from commit be08ec9)
This commit is contained in:
Gerrit Meier
2017-10-09 15:17:41 +02:00
parent 94bbc1eb50
commit 188c165174
7 changed files with 206 additions and 32 deletions

View File

@@ -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);
}
}
}

View File

@@ -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<String, Object> resolveParams(Object[] parameters) {
Map<String, Object> resolveParams(Object[] parameters) {
Map<String, Object> 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

View File

@@ -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));
}
}

View File

@@ -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");
}
}
}

View File

@@ -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;
}
}

View File

@@ -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<SampleEntityForNamedQuery, Long> {
@Query("MATCH (e) WHERE e.name='test' RETURN e")
SampleEntityForNamedQuery getTitleEntity();
SampleEntityForNamedQuery findByName(String name);
SampleEntityForNamedQuery findByQueryWithoutParameter();
SampleEntityForNamedQuery findByQueryWithParameter(@Param("name") String name);
}

View File

@@ -0,0 +1,2 @@
SampleEntityForNamedQuery.findByQueryWithoutParameter=MATCH (e) WHERE e.name='test' RETURN e
SampleEntityForNamedQuery.findByQueryWithParameter=MATCH (e) WHERE e.name={name} RETURN e