From 63742c55f01ef66883683ca24ef1675b8fefb239 Mon Sep 17 00:00:00 2001 From: Michael Hunger Date: Mon, 25 Jul 2011 16:10:45 +0200 Subject: [PATCH] added gremlin REST addon, parameters for queries, updated documentation --- .../neo4j/rest/RestCypherQueryEngine.java | 12 +- .../rest/support/RestQueryEngineTest.java | 4 +- .../data/neo4j/annotation/Query.java | 4 +- .../neo4j/conversion/QueryResultBuilder.java | 2 +- .../data/neo4j/core/NodeBacked.java | 9 ++ .../QueryFieldAccessorFactory.java | 34 ++-- .../TraversalFieldAccessorFactory.java | 12 +- .../repository/GraphRepositoryFactory.java | 50 +++--- .../neo4j/support/node/Neo4jNodeBacking.aj | 15 +- .../support/query/CypherQueryExecutor.java | 17 +- .../neo4j/support/query/QueryOperations.java | 6 +- .../springframework/data/neo4j/Person.java | 8 +- .../data/neo4j/PersonRepository.java | 23 +-- .../neo4j/support/GraphRepositoryTest.java | 6 +- .../neo4j/support/query/QueryEngineTest.java | 12 +- .../support/query/QueryExecutorTest.java | 120 -------------- .../support/query/QueryOperationsTest.java | 152 ------------------ .../META-INF/graph-named-queries.properties | 2 +- .../Neo4jGraphPersistenceTest-context.xml | 2 +- .../reference/programming-model/aspectj.xml | 9 ++ .../programming-model/introducedmethods.xml | 6 +- .../programming-model/node-entities.xml | 27 ++-- .../programming-model/repositories.xml | 16 +- 23 files changed, 158 insertions(+), 390 deletions(-) delete mode 100644 spring-data-neo4j/src/test/java/org/springframework/data/neo4j/support/query/QueryExecutorTest.java delete mode 100644 spring-data-neo4j/src/test/java/org/springframework/data/neo4j/support/query/QueryOperationsTest.java diff --git a/spring-data-neo4j-rest/src/main/java/org/springframework/data/neo4j/rest/RestCypherQueryEngine.java b/spring-data-neo4j-rest/src/main/java/org/springframework/data/neo4j/rest/RestCypherQueryEngine.java index 2906ffaa3..219b8d462 100644 --- a/spring-data-neo4j-rest/src/main/java/org/springframework/data/neo4j/rest/RestCypherQueryEngine.java +++ b/spring-data-neo4j-rest/src/main/java/org/springframework/data/neo4j/rest/RestCypherQueryEngine.java @@ -17,10 +17,13 @@ package org.springframework.data.neo4j.rest; +import org.neo4j.helpers.collection.MapUtil; import org.springframework.data.neo4j.conversion.*; import org.springframework.data.neo4j.support.query.QueryEngine; -import java.util.*; +import java.util.Iterator; +import java.util.List; +import java.util.Map; /** * @author mh @@ -42,11 +45,8 @@ public class RestCypherQueryEngine implements QueryEngine> { @Override public QueryResult> query(String statement, Map params) { - return executeStatement(statement); - } - - private RestQueryResult executeStatement(String statement) { - final RequestResult requestResult = restRequest.get("ext/CypherPlugin/graphdb/execute_query", JsonHelper.createJsonFrom(Collections.singletonMap("query", statement))); + final String parametrizedStatement = QueryResultBuilder.replaceParams(statement, params); + final RequestResult requestResult = restRequest.get("ext/CypherPlugin/graphdb/execute_query", JsonHelper.createJsonFrom(MapUtil.map("query", parametrizedStatement))); return new RestQueryResult(restRequest.toMap(requestResult),restGraphDatabase,resultConverter); } diff --git a/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/support/RestQueryEngineTest.java b/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/support/RestQueryEngineTest.java index d39b179b5..771a09131 100644 --- a/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/support/RestQueryEngineTest.java +++ b/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/support/RestQueryEngineTest.java @@ -22,7 +22,7 @@ import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.neo4j.core.GraphDatabase; import org.springframework.data.neo4j.rest.RestGraphDatabase; -import org.springframework.data.neo4j.support.query.QueryOperationsTest; +import org.springframework.data.neo4j.support.query.QueryEngineTest; import org.springframework.test.context.CleanContextCacheTestExecutionListener; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.TestExecutionListeners; @@ -39,7 +39,7 @@ import org.springframework.test.context.transaction.TransactionalTestExecutionLi @ContextConfiguration(locations = {"classpath:org/springframework/data/neo4j/support/Neo4jGraphPersistenceTest-context.xml", "classpath:RestTest-context.xml"}) @TestExecutionListeners({CleanContextCacheTestExecutionListener.class, DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class}) -public class RestQueryEngineTest extends QueryOperationsTest { +public class RestQueryEngineTest extends QueryEngineTest { @Autowired RestGraphDatabase restGraphDatabase; diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/annotation/Query.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/annotation/Query.java index f9b5793e6..49901a417 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/annotation/Query.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/annotation/Query.java @@ -36,7 +36,7 @@ import java.lang.annotation.Target; @Target({ElementType.FIELD,ElementType.METHOD}) public @interface Query { /** - * @return Query to be executed %d will be replaced by the node-id of the current entity other placeholders by the given params + * @return Query to be executed %start will be replaced by the node-id of the current entity other placeholders (%name) by the given named params */ String value() default ""; @@ -46,7 +46,7 @@ public @interface Query { Class elementClass() default Object.class; /** - * @return parameters that are replaced in the to the @see query-string + * @return tuple list of parameters that are replaced in the to the @see query-string {"name", value} */ String[] params() default {}; } diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/conversion/QueryResultBuilder.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/conversion/QueryResultBuilder.java index 3c820967b..5e1e932b1 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/conversion/QueryResultBuilder.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/conversion/QueryResultBuilder.java @@ -46,7 +46,7 @@ public class QueryResultBuilder implements QueryResult { public static String replaceParams(String statement, Map params) { if (params==null || params.isEmpty()) return statement; for (Map.Entry param : params.entrySet()) { - statement = statement.replaceAll(":"+param.getKey(),""+param.getValue()); + statement = statement.replaceAll("%"+param.getKey()+"\\b",""+param.getValue()); } return statement; } diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/core/NodeBacked.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/core/NodeBacked.java index e9a64efb1..bde63c6f8 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/core/NodeBacked.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/core/NodeBacked.java @@ -19,6 +19,10 @@ package org.springframework.data.neo4j.core; import org.neo4j.graphdb.Node; import org.neo4j.graphdb.Relationship; import org.neo4j.graphdb.traversal.TraversalDescription; +import org.springframework.data.neo4j.support.node.Neo4jNodeBacking; +import org.springframework.data.neo4j.support.query.CypherQueryExecutor; + +import java.util.Map; /** * Interface introduced to objects annotated with @NodeEntity by the {@link org.springframework.data.neo4j.support.node.Neo4jNodeBacking} aspect. @@ -125,6 +129,11 @@ public interface NodeBacked extends GraphBacked { R getRelationshipTo(NodeBacked target, Class relationshipClass, String type); + Iterable findAllByQuery(final String query, final Class targetType,Map params); + + Iterable> findAllByQuery(final String query,Map params); + + T findByQuery(final String query, final Class targetType,Map params); diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/fieldaccess/QueryFieldAccessorFactory.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/fieldaccess/QueryFieldAccessorFactory.java index 14058ed62..b739fd971 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/fieldaccess/QueryFieldAccessorFactory.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/fieldaccess/QueryFieldAccessorFactory.java @@ -22,6 +22,7 @@ import org.springframework.data.neo4j.core.NodeBacked; import org.springframework.data.neo4j.support.GenericTypeExtractor; import java.lang.reflect.Field; +import java.util.HashMap; import java.util.Map; import static org.springframework.data.neo4j.support.DoReturn.doReturn; @@ -48,13 +49,16 @@ public class QueryFieldAccessorFactory implements FieldAccessorFactory target; - protected String[] params; + protected String[] annotationParams; private boolean iterableResult; public QueryFieldAccessor(final Field field) { this.field = field; final Query query = field.getAnnotation(Query.class); - this.params = query.params(); + this.annotationParams = query.params(); + if ((this.annotationParams.length % 2) != 0) { + throw new IllegalArgumentException("Number of parameters has to be even to construct a parameter map"); + } this.query = query.value(); this.iterableResult = Iterable.class.isAssignableFrom(field.getType()); this.target = resolveTarget(query,field); @@ -77,23 +81,23 @@ public class QueryFieldAccessorFactory implements FieldAccessorFactory params) { + if (!iterableResult) return nodeBacked.findByQuery(queryString,this.target,params); + if (Map.class.isAssignableFrom(target)) return nodeBacked.findAllByQuery(queryString,params); + return nodeBacked.findAllByQuery(queryString, this.target,params); } - private Object[] createPlaceholderParams(NodeBacked nodeBacked) { - if (params.length==0) return new Object[] {nodeBacked.getNodeId()}; - - final Object[] parameters = new Object[1 + this.params.length]; - parameters[0]=nodeBacked.getNodeId(); - System.arraycopy(this.params,0,parameters,1,this.params.length); - return parameters; + private Map createPlaceholderParams(NodeBacked nodeBacked) { + Map params=new HashMap(); + params.put("start",nodeBacked.getNodeId()); + if (annotationParams.length==0) return params; + for (int i = 0; i < annotationParams.length; i+=2) { + params.put(annotationParams[i],annotationParams[i+1]); + } + return params; } } } diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/fieldaccess/TraversalFieldAccessorFactory.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/fieldaccess/TraversalFieldAccessorFactory.java index 668c5578d..a0bcc39ba 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/fieldaccess/TraversalFieldAccessorFactory.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/fieldaccess/TraversalFieldAccessorFactory.java @@ -19,9 +19,11 @@ package org.springframework.data.neo4j.fieldaccess; import org.neo4j.graphdb.traversal.TraversalDescription; import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.data.neo4j.annotation.GraphTraversal; +import org.springframework.data.neo4j.annotation.Query; import org.springframework.data.neo4j.core.FieldTraversalDescriptionBuilder; import org.springframework.data.neo4j.core.NodeBacked; import org.springframework.data.neo4j.repository.DirectGraphRepositoryFactory; +import org.springframework.data.neo4j.support.GenericTypeExtractor; import java.lang.reflect.Constructor; import java.lang.reflect.Field; @@ -56,11 +58,19 @@ public class TraversalFieldAccessorFactory implements FieldAccessorFactory resolveTarget(GraphTraversal graphTraversal, Field field) { + if (!graphTraversal.elementClass().equals(Object.class)) return graphTraversal.elementClass(); + final Class result = GenericTypeExtractor.resolveFieldType(field); + if (!NodeBacked.class.isAssignableFrom(result)) throw new IllegalArgumentException("The target result type of the traversal is no node entity: "+field); + return (Class) result; + } + + @Override public boolean isWriteable(NodeBacked nodeBacked) { return false; diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/GraphRepositoryFactory.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/GraphRepositoryFactory.java index f443c4a57..5ebcf82b4 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/GraphRepositoryFactory.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/GraphRepositoryFactory.java @@ -38,6 +38,7 @@ import org.springframework.util.Assert; import java.io.Serializable; import java.lang.reflect.Method; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -150,19 +151,28 @@ public class GraphRepositoryFactory extends RepositoryFactorySupport { private String prepareQuery(Object[] args) { final Parameters parameters = getParameters(); - Object[] resolvedParameters = resolveParameters(args,parameters.getBindableParameters()); - String baseQuery = String.format(query, (Object[]) resolvedParameters); + String queryString = this.query; if (parameters.hasSortParameter()) { - baseQuery = addSorting(baseQuery, (Sort) args[parameters.getSortIndex()]); + queryString = addSorting(queryString, (Sort) args[parameters.getSortIndex()]); } if (parameters.hasPageableParameter()) { final Pageable pageable = getPageable(args); if (pageable!=null) { - baseQuery = addSorting(baseQuery, pageable.getSort()); - baseQuery = addPaging(baseQuery, pageable); + queryString = addSorting(queryString, pageable.getSort()); + queryString = addPaging(queryString, pageable); } } - return baseQuery; + return queryString; + } + + + private Map resolveParams(Object[] parameters) { + Map params=new HashMap(); + for (Parameter parameter : getParameters().getBindableParameters()) { + final Object value = parameters[parameter.getIndex()]; + params.put(parameter.getName(),resolveParameter(value)); + } + return params; } private Pageable getPageable(Object[] args) { @@ -191,17 +201,6 @@ public class GraphRepositoryFactory extends RepositoryFactorySupport { return result; } - private Object[] resolveParameters(Object[] parameters, Parameters bindableParameters) { - final int paramCount = bindableParameters.getNumberOfParameters(); - final Object[] result = new Object[paramCount]; - for (int i = 0; i < paramCount; i++) { - final Parameter parameter = bindableParameters.getParameter(i); - final Object value = parameters[parameter.getIndex()]; - result[i] = resolveParameter(value); - } - return result; - } - private Object resolveParameter(Object parameter) { if (parameter instanceof NodeBacked) { return ((NodeBacked)parameter).getNodeId(); @@ -251,24 +250,25 @@ public class GraphRepositoryFactory extends RepositoryFactorySupport { @Override public Object execute(Object[] parameters) { + Map params = queryMethod.resolveParams(parameters); final String queryString = queryMethod.prepareQuery(parameters); - return dispatchQuery(queryString,queryMethod.getPageable(parameters)); + return dispatchQuery(queryString,params,queryMethod.getPageable(parameters)); } - private Object dispatchQuery(String queryString, Pageable pageable) { + private Object dispatchQuery(String queryString, Map params, Pageable pageable) { final QueryMethod.Type queryResultType = queryMethod.getType(); if (queryResultType== QueryMethod.Type.PAGING) { - return queryPaged(queryString,pageable); + return queryPaged(queryString,params,pageable); } if (iterableResult) { - if (compoundType.isAssignableFrom(Map.class)) return queryExecutor.queryForList(queryString); - return queryExecutor.query(queryString, queryMethod.getCompoundType()); + if (compoundType.isAssignableFrom(Map.class)) return queryExecutor.queryForList(queryString,params); + return queryExecutor.query(queryString, queryMethod.getCompoundType(),params); } - return queryExecutor.queryForObject(queryString, queryMethod.getReturnType()); + return queryExecutor.queryForObject(queryString, queryMethod.getReturnType(),params); } - private Object queryPaged(String queryString, Pageable pageable) { - final Iterable result = queryExecutor.query(queryString, queryMethod.getCompoundType()); + private Object queryPaged(String queryString, Map params, Pageable pageable) { + final Iterable result = queryExecutor.query(queryString, queryMethod.getCompoundType(),params); return createPage(result, pageable); } diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/node/Neo4jNodeBacking.aj b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/node/Neo4jNodeBacking.aj index 2e9a3d358..94f3a35c7 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/node/Neo4jNodeBacking.aj +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/node/Neo4jNodeBacking.aj @@ -31,6 +31,7 @@ import org.springframework.data.neo4j.annotation.RelationshipEntity; import org.springframework.data.neo4j.annotation.RelatedTo; import org.springframework.data.neo4j.annotation.GraphProperty; import org.springframework.data.neo4j.annotation.GraphId; +import org.springframework.data.neo4j.annotation.Query; import org.springframework.data.neo4j.annotation.RelatedToVia; import org.springframework.data.neo4j.annotation.GraphTraversal; @@ -71,6 +72,7 @@ public aspect Neo4jNodeBacking { // extends AbstractTypeAnnotatingMixinFields(traverser, targetType, Neo4jNodeBacking.aspectOf().graphDatabaseContext); } - public Iterable NodeBacked.findAllByQuery(final String query, final Class targetType) { + + public Iterable NodeBacked.findAllByQuery(final String query, final Class targetType, Map params) { final CypherQueryExecutor executor = new CypherQueryExecutor(Neo4jNodeBacking.aspectOf().graphDatabaseContext); - return executor.query(query, targetType); + return executor.query(query, targetType,params); } - public Iterable> NodeBacked.findAllByQuery(final String query) { + public Iterable> NodeBacked.findAllByQuery(final String query,Map params) { final CypherQueryExecutor executor = new CypherQueryExecutor(Neo4jNodeBacking.aspectOf().graphDatabaseContext); - return executor.queryForList(query); + return executor.queryForList(query,params); } - public T NodeBacked.findByQuery(final String query, final Class targetType) { + public T NodeBacked.findByQuery(final String query, final Class targetType,Map params) { final CypherQueryExecutor executor = new CypherQueryExecutor(Neo4jNodeBacking.aspectOf().graphDatabaseContext); - return executor.queryForObject(query, targetType); + return executor.queryForObject(query, targetType,params); } public Iterable> NodeBacked.findAllPathsByTraversal(TraversalDescription traversalDescription) { diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/query/CypherQueryExecutor.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/query/CypherQueryExecutor.java index 8262005ff..9a62c8bcf 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/query/CypherQueryExecutor.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/query/CypherQueryExecutor.java @@ -20,7 +20,6 @@ import org.springframework.data.neo4j.support.GraphDatabaseContext; import org.springframework.data.neo4j.support.conversion.EntityResultConverter; import java.util.Collections; -import java.util.HashMap; import java.util.Map; /** @@ -36,23 +35,19 @@ public class CypherQueryExecutor implements QueryOperations> queryEngine = new CypherQueryEngine(ctx.getGraphDatabaseService(), converter); } - public Iterable> queryForList(String statement, Map...params) { + public Iterable> queryForList(String statement, Map params) { return queryEngine.query(statement,mergeParams(params)); } - public Iterable query(String statement, Class type, Map...params) { + public Iterable query(String statement, Class type, Map params) { return queryEngine.query(statement,mergeParams(params)).to(type); } - public T queryForObject(String statement, Class type, Map...params) { + public T queryForObject(String statement, Class type, Map params) { return (T) queryEngine.query(statement,mergeParams(params)).to(type).single(); } - private Map mergeParams(Map...params) { - if (params==null || params.length==0) return Collections.emptyMap(); - Map result=new HashMap(); - for (Map map : params) { - result.putAll(map); - } - return result; + private Map mergeParams(Map params) { + if (params==null) return Collections.emptyMap(); + return params; } } \ No newline at end of file diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/query/QueryOperations.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/query/QueryOperations.java index 5c5f2cf7a..69bea6771 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/query/QueryOperations.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/query/QueryOperations.java @@ -23,9 +23,9 @@ import java.util.Map; * @since 28.06.11 */ public interface QueryOperations { - Iterable queryForList(String statement, Map...params); + Iterable queryForList(String statement, Map params); - Iterable query(String statement, Class type, Map...params); + Iterable query(String statement, Class type, Map params); - T queryForObject(String statement, Class type, Map...params); + T queryForObject(String statement, Class type, Map params); } diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/Person.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/Person.java index 338a34826..c5c4ec449 100644 --- a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/Person.java +++ b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/Person.java @@ -66,16 +66,16 @@ public class Person { @RelatedToVia(type = "knows", elementClass = Friendship.class) private Iterable friendships; - @Query(value = "start person=(%d) match (person)<-[:boss]-(boss) return boss") + @Query(value = "start person=(%start) match (person)<-[:boss]-(boss) return boss") private Person bossByQuery; - @Query(value = "start person=(%d) match (person)<-[:boss]-(boss) return boss.%s",params = "name") + @Query(value = "start person=(%start) match (person)<-[:boss]-(boss) return boss.%property",params = {"property","name"}) private String bossName; - @Query(value = "start person=(%d) match (person)<-[:persons]-(team)-[:persons]->(member) return member",elementClass = Person.class) + @Query(value = "start person=(%start) match (person)<-[:persons]-(team)-[:persons]->(member) return member",elementClass = Person.class) private Iterable otherTeamMembers; - @Query(value = "start person=(%d) match (person)<-[:persons]-(team)-[:persons]->(member) return member.name, member.age") + @Query(value = "start person=(%start) match (person)<-[:persons]-(team)-[:persons]->(member) return member.name, member.age") private Iterable> otherTeamMemberData; public String getBossName() { diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/PersonRepository.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/PersonRepository.java index 19e57094f..0008ba2a3 100644 --- a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/PersonRepository.java +++ b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/PersonRepository.java @@ -22,6 +22,7 @@ import org.springframework.data.domain.Sort; import org.springframework.data.neo4j.annotation.Query; import org.springframework.data.neo4j.repository.GraphRepository; import org.springframework.data.neo4j.repository.NamedIndexRepository; +import org.springframework.data.repository.query.Param; import java.util.Map; @@ -31,19 +32,19 @@ import java.util.Map; */ public interface PersonRepository extends GraphRepository, NamedIndexRepository { - @Query("start team=(%d) match (team)-[:persons]->(member) return member") - Iterable findAllTeamMembers(Group team); + @Query("start team=(%team) match (team)-[:persons]->(member) return member") + Iterable findAllTeamMembers(@Param("team") Group team); - @Query("start team=(%d) match (team)-[:persons]->(member) return member.name,member.age") - Iterable> findAllTeamMemberData(Group team); + @Query("start team=(%team) match (team)-[:persons]->(member) return member.name,member.age") + Iterable> findAllTeamMemberData(@Param("team") Group team); - @Query("start person=(%d) match (boss)-[:boss]->(person) return boss") - Person findBoss(Person person); + @Query("start person=(%person) match (boss)-[:boss]->(person) return boss") + Person findBoss(@Param("person") Person person); - Group findTeam(Person person); + Group findTeam(@Param("person") Person person); - @Query("start team=(%d) match (team)-[:persons]->(member) return member") - Page findAllTeamMembersPaged(Pageable page, Group team); - @Query("start team=(%d) match (team)-[:persons]->(member) return member") - Iterable findAllTeamMembersSorted(Group team, Sort sort); + @Query("start team=(%team) match (team)-[:persons]->(member) return member") + Page findAllTeamMembersPaged(@Param("team") Group team, Pageable page); + @Query("start team=(%team) match (team)-[:persons]->(member) return member") + Iterable findAllTeamMembersSorted(@Param("team") Group team, Sort sort); } diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/support/GraphRepositoryTest.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/support/GraphRepositoryTest.java index 5e7a7c92b..c1bbd23a2 100644 --- a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/support/GraphRepositoryTest.java +++ b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/support/GraphRepositoryTest.java @@ -93,21 +93,21 @@ public class GraphRepositoryTest { @Transactional public void testFindPaged() { final PageRequest page = new PageRequest(0, 1, Sort.Direction.ASC, "member.name"); - Page teamMemberPage1 = personRepository.findAllTeamMembersPaged(page, testTeam.sdg); + Page teamMemberPage1 = personRepository.findAllTeamMembersPaged(testTeam.sdg,page); assertThat(teamMemberPage1, hasItem(testTeam.david)); } @Test @Transactional public void testFindPagedDescending() { final PageRequest page = new PageRequest(0, 2, Sort.Direction.DESC, "member.name"); - Page teamMemberPage1 = personRepository.findAllTeamMembersPaged(page, testTeam.sdg); + Page teamMemberPage1 = personRepository.findAllTeamMembersPaged(testTeam.sdg,page); assertEquals(asList(testTeam.michael, testTeam.emil), asCollection(teamMemberPage1)); assertThat(teamMemberPage1.isFirstPage(), is(true)); } @Test @Transactional public void testFindPagedNull() { - Page teamMemberPage1 = personRepository.findAllTeamMembersPaged(null, testTeam.sdg); + Page teamMemberPage1 = personRepository.findAllTeamMembersPaged(testTeam.sdg,null); assertEquals(asList(testTeam.michael, testTeam.emil,testTeam.david), asCollection(teamMemberPage1)); assertThat(teamMemberPage1.isFirstPage(), is(true)); assertThat(teamMemberPage1.isLastPage(), is(false)); diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/support/query/QueryEngineTest.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/support/query/QueryEngineTest.java index 70baa7b31..0c84c2b87 100644 --- a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/support/query/QueryEngineTest.java +++ b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/support/query/QueryEngineTest.java @@ -86,7 +86,7 @@ public class QueryEngineTest { @Test @Transactional public void testQueryList() throws Exception { - final String queryString = "start person=(:michael,:david) return person.name, person.age"; + final String queryString = "start person=(%michael,%david) return person.name, person.age"; final Collection> result = IteratorUtil.asCollection(queryEngine.query(queryString, MapUtil.map("michael",idFor(michael), "david",idFor(testTeam.david)))); assertEquals(asList(testTeam.simpleRowFor(michael,"person"),testTeam.simpleRowFor(testTeam.david,"person")),result); @@ -94,14 +94,14 @@ public class QueryEngineTest { @Test public void testQueryListOfTypeNode() throws Exception { - final String queryString = "start person=(name_index,name,\":name\") match (person) <-[:boss]- (boss) return boss"; + final String queryString = "start person=(name_index,name,\"%name\") match (person) <-[:boss]- (boss) return boss"; final Collection result = IteratorUtil.asCollection(queryEngine.query(queryString, michaelsName()).to(Node.class)); assertEquals(asList(nodeFor(testTeam.emil)),result); } @Test public void testQueryListOfTypePerson() throws Exception { - final String queryString = "start person=(name_index,name,\":name\") match (person) <-[:boss]- (boss) return boss"; + final String queryString = "start person=(name_index,name,\"%name\") match (person) <-[:boss]- (boss) return boss"; final Collection result = IteratorUtil.asCollection(queryEngine.query(queryString, michaelsName()).to(Person.class, new EntityResultConverter(graphDatabaseContext))); assertEquals(asList(testTeam.emil),result); @@ -113,7 +113,7 @@ public class QueryEngineTest { @Test public void testQuerySingleOfTypePerson() throws Exception { - final String queryString = "start person=(name_index,name,\":name\") match (person) <-[:boss]- (boss) return boss"; + final String queryString = "start person=(name_index,name,\"%name\") match (person) <-[:boss]- (boss) return boss"; final Person result = queryEngine.query(queryString, michaelsName()).to(Person.class, new EntityResultConverter,Person>(graphDatabaseContext)).single(); assertEquals(testTeam.emil,result); @@ -141,14 +141,14 @@ public class QueryEngineTest { @Test public void testQueryForObjectAsString() throws Exception { - final String queryString = "start person=(name_index,name,\":name\") match (person) <-[:persons]- (team) return team.name"; + final String queryString = "start person=(name_index,name,\"%name\") match (person) <-[:persons]- (team) return team.name"; final String result = queryEngine.query(queryString, michaelsName()).to(String.class).single(); assertEquals(testTeam.sdg.getName(),result); } @Test public void testQueryForObjectAsEnum() throws Exception { - final String queryString = "start person=(name_index,name,\":name\") return person.personality"; + final String queryString = "start person=(name_index,name,\"%name\") return person.personality"; final Personality result = queryEngine.query(queryString, michaelsName()).to(Personality.class).single(); assertEquals(michael.getPersonality(),result); diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/support/query/QueryExecutorTest.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/support/query/QueryExecutorTest.java deleted file mode 100644 index ef8d10ac6..000000000 --- a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/support/query/QueryExecutorTest.java +++ /dev/null @@ -1,120 +0,0 @@ -/** - * Copyright 2011 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 - * - * http://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.support.query; - -import org.junit.Before; -import org.junit.Test; -import org.junit.internal.matchers.IsCollectionContaining; -import org.junit.runner.RunWith; -import org.neo4j.helpers.collection.IteratorUtil; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.neo4j.Group; -import org.springframework.data.neo4j.Person; -import org.springframework.data.neo4j.Personality; -import org.springframework.data.neo4j.support.GraphDatabaseContext; -import org.springframework.data.neo4j.support.TestTeam; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.transaction.annotation.Transactional; - -import java.util.Collection; -import java.util.Map; - -import static java.util.Arrays.asList; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; - -/** - * @author mh - * @since 13.06.11 - */ -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = {"classpath:org/springframework/data/neo4j/support/Neo4jGraphPersistenceTest-context.xml"}) -@Transactional -public class QueryExecutorTest { - @Autowired - GraphDatabaseContext graphDatabaseContext; - private CypherQueryExecutor queryExecutor; - private TestTeam testTeam; - private Person michael; - - @Before - public void setUp() throws Exception { - testTeam = new TestTeam(); - testTeam.createSDGTeam(); - queryExecutor = new CypherQueryExecutor(graphDatabaseContext); - michael = testTeam.michael; - } - - @Test - @Transactional - public void testQueryList() throws Exception { - final String queryString = String.format("start person=(%d,%d) return person.name, person.age", michael.getNodeId(), testTeam.david.getNodeId()); - final Collection> result = IteratorUtil.asCollection(queryExecutor.queryForList(queryString)); - - assertEquals(asList(testTeam.simpleRowFor(michael,"person"),testTeam.simpleRowFor(testTeam.david,"person")),result); - } - - @Test - public void testQueryListOfTypePerson() throws Exception { - final String queryString = String.format("start person=(name_index,name,\"%s\") match (person) <-[:boss]- (boss) return boss", michael.getName()); - final Collection result = IteratorUtil.asCollection(queryExecutor.query(queryString, Person.class)); - - assertEquals(asList(testTeam.emil),result); - - } - - @Test - public void testQueryOtherTeamMembers() throws Exception { - final String queryString = String.format("start person=(%d) match (person)<-[:persons]-(team)-[:persons]->(member) return member", michael.getNodeId()); - System.out.println("testTeam = " + testTeam.sdg.getPersons()); - final Collection result = IteratorUtil.asCollection(queryExecutor.query(queryString, Person.class)); - - assertThat(result, IsCollectionContaining.hasItems(testTeam.david, testTeam.emil)); - - } - - @Test - public void testQueryAllTeamMembersByTeam() throws Exception { - final String queryString = String.format("start team=(Group,name,\"%s\") match (team)-[:persons]->(member) return member", testTeam.sdg.getName()); - final Collection result = IteratorUtil.asCollection(queryExecutor.query(queryString, Person.class)); - - assertThat(result, IsCollectionContaining.hasItems(testTeam.david,testTeam.michael)); - } - - @Test - public void testQueryForObjectAsGroup() throws Exception { - final String queryString = String.format("start person=(name_index,name,\"%s\") match (person) <-[:persons]- (team) return team", michael.getName()); - final Group result = queryExecutor.queryForObject(queryString, Group.class); - - assertEquals(testTeam.sdg,result); - } - @Test - public void testQueryForObjectAsString() throws Exception { - final String queryString = String.format("start person=(name_index,name,\"%s\") match (person) <-[:persons]- (team) return team.name", michael.getName()); - final String result = queryExecutor.queryForObject(queryString, String.class); - - assertEquals(testTeam.sdg.getName(),result); - } - @Test - public void testQueryForObjectAsEnum() throws Exception { - final String queryString = String.format("start person=(name_index,name,\"%s\") return person.personality", michael.getName()); - final Personality result = queryExecutor.queryForObject(queryString, Personality.class); - - assertEquals(michael.getPersonality(),result); - } -} diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/support/query/QueryOperationsTest.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/support/query/QueryOperationsTest.java deleted file mode 100644 index bb690a97a..000000000 --- a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/support/query/QueryOperationsTest.java +++ /dev/null @@ -1,152 +0,0 @@ -/** - * Copyright 2011 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 - * - * http://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.support.query; - -import org.junit.Before; -import org.junit.Test; -import org.junit.internal.matchers.IsCollectionContaining; -import org.junit.runner.RunWith; -import org.neo4j.graphdb.Node; -import org.neo4j.helpers.collection.IteratorUtil; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.convert.ConversionService; -import org.springframework.data.neo4j.Person; -import org.springframework.data.neo4j.Personality; -import org.springframework.data.neo4j.core.GraphDatabase; -import org.springframework.data.neo4j.core.NodeBacked; -import org.springframework.data.neo4j.Person; -import org.springframework.data.neo4j.Personality; -import org.springframework.data.neo4j.support.DelegatingGraphDatabase; -import org.springframework.data.neo4j.support.GraphDatabaseContext; -import org.springframework.data.neo4j.support.TestTeam; -import org.springframework.data.neo4j.support.node.Neo4jHelper; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.context.transaction.BeforeTransaction; -import org.springframework.transaction.annotation.Transactional; - -import java.util.Collection; -import java.util.Map; - -import static java.util.Arrays.asList; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; - - -/** - * @author mh - * @since 13.06.11 - */ -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = {"classpath:org/springframework/data/neo4j/support/Neo4jGraphPersistenceTest-context.xml"}) -@Transactional -public class QueryOperationsTest { - @Autowired - protected ConversionService conversionService; - @Autowired - private GraphDatabaseContext graphDatabaseContext; - private CypherQueryExecutor queryOperations; - private TestTeam testTeam; - private Person michael; - private GraphDatabase graphDatabase; - - @Before - public void setUp() throws Exception { - graphDatabase = createGraphDatabase(); - testTeam = new TestTeam(); - testTeam.createSDGTeam(); - queryOperations = new CypherQueryExecutor(graphDatabaseContext); - //new DefaultQueryOperations>(graphDatabase.queryEngineFor(QueryEngine.Type.Cypher)); - michael = testTeam.michael; - } - - @BeforeTransaction - public void cleanDb() { - Neo4jHelper.cleanDb(graphDatabaseContext); - } - - protected GraphDatabase createGraphDatabase() throws Exception { - final DelegatingGraphDatabase graphDatabase = new DelegatingGraphDatabase(graphDatabaseContext.getGraphDatabaseService()); - graphDatabase.setConversionService(conversionService); - return graphDatabase; - } - - @Test - @Transactional - public void testQueryList() throws Exception { - final String queryString = String.format("start person=(%d,%d) return person.name, person.age", idFor(michael), idFor(testTeam.david)); - final Collection> result = IteratorUtil.asCollection(queryOperations.queryForList(queryString)); - - assertEquals(asList(testTeam.simpleRowFor(michael,"person"),testTeam.simpleRowFor(testTeam.david,"person")),result); - } - - @Test - public void testQueryListOfTypePerson() throws Exception { - final String queryString = String.format("start person=(name_index,name,\"%s\") match (person) <-[:boss]- (boss) return boss", michael.getName()); - final Collection result = IteratorUtil.asCollection(queryOperations.query(queryString, Node.class)); - - assertEquals(asList(nodeFor(testTeam.emil)),result); - - } - - private Node nodeFor(final NodeBacked entity) { - return entity.getPersistentState(); - } - private long idFor(final NodeBacked entity) { - return entity.getNodeId(); - } - - @Test - public void testQueryOtherTeamMembers() throws Exception { - final String queryString = String.format("start person=(%d) match (person)<-[:persons]-(team)-[:persons]->(member) return member", idFor(michael)); - System.out.println("testTeam = " + testTeam.sdg.getPersons()); - final Collection result = IteratorUtil.asCollection(queryOperations.query(queryString, Node.class)); - - assertThat(result, IsCollectionContaining.hasItems(nodeFor(testTeam.david), nodeFor(testTeam.emil))); - - } - - @Test - public void testQueryAllTeamMembersByTeam() throws Exception { - final String queryString = String.format("start team=(Group,name,\"%s\") match (team)-[:persons]->(member) return member", testTeam.sdg.getName()); - final Collection result = IteratorUtil.asCollection(queryOperations.query(queryString, Node.class)); - - assertThat(result, IsCollectionContaining.hasItems(nodeFor(testTeam.david),nodeFor(testTeam.michael))); - } - - @Test - public void testQueryForObjectAsGroup() throws Exception { - final String queryString = String.format("start person=(name_index,name,\"%s\") match (person) <-[:persons]- (team) return team", michael.getName()); - final Node result = queryOperations.queryForObject(queryString, Node.class); - - assertEquals(nodeFor(testTeam.sdg),result); - } - @Test - public void testQueryForObjectAsString() throws Exception { - final String queryString = String.format("start person=(name_index,name,\"%s\") match (person) <-[:persons]- (team) return team.name", michael.getName()); - final String result = queryOperations.queryForObject(queryString, String.class); - - assertEquals(testTeam.sdg.getName(),result); - } - @Test - public void testQueryForObjectAsEnum() throws Exception { - final String queryString = String.format("start person=(name_index,name,\"%s\") return person.personality", michael.getName()); - final Personality result = queryOperations.queryForObject(queryString, Personality.class); - - assertEquals(michael.getPersonality(),result); - } -} diff --git a/spring-data-neo4j/src/test/resources/META-INF/graph-named-queries.properties b/spring-data-neo4j/src/test/resources/META-INF/graph-named-queries.properties index d2e4b9180..a92b0a402 100644 --- a/spring-data-neo4j/src/test/resources/META-INF/graph-named-queries.properties +++ b/spring-data-neo4j/src/test/resources/META-INF/graph-named-queries.properties @@ -1 +1 @@ -Person.findTeam=start p=(%d) match (p)<-[:persons]-(group) return group \ No newline at end of file +Person.findTeam=start p=(%person) match (p)<-[:persons]-(group) return group \ No newline at end of file diff --git a/spring-data-neo4j/src/test/resources/org/springframework/data/neo4j/support/Neo4jGraphPersistenceTest-context.xml b/spring-data-neo4j/src/test/resources/org/springframework/data/neo4j/support/Neo4jGraphPersistenceTest-context.xml index 198b29d6f..16d0554e7 100644 --- a/spring-data-neo4j/src/test/resources/org/springframework/data/neo4j/support/Neo4jGraphPersistenceTest-context.xml +++ b/spring-data-neo4j/src/test/resources/org/springframework/data/neo4j/support/Neo4jGraphPersistenceTest-context.xml @@ -150,7 +150,7 @@ - start p=(%d) match (p)<-[:persons]-(group) return group + start p=(%person) match (p)<-[:persons]-(group) return group diff --git a/src/docbkx/reference/programming-model/aspectj.xml b/src/docbkx/reference/programming-model/aspectj.xml index 0765890d4..f40b7a951 100644 --- a/src/docbkx/reference/programming-model/aspectj.xml +++ b/src/docbkx/reference/programming-model/aspectj.xml @@ -48,6 +48,15 @@ The current version that does not show incorrect errors is AspectJ 1.6.12.M1 (included in STS 2.7.0.M2), previous versions are reported to mislead the user. + + + There might be some issues with the eclipse maven plugin not adding AspectJ files correctly to the build path. If you encounter issues, please try the following: + + Try editing the build path to include **/*.aj for the spring-data-neo4j project. + You can do this by selecting "Build Path -> Configure Build Path ..." from the Package Explorer. + Then for the spring-data-neo4j/src/main/java add **/*.aj to the Included path. + + The AspectJ support in IntelliJ IDEA lacks some of the features. JetBrains is working on improving the situation in their upcoming 10.5 release of their popular IDE. Their latest work is available diff --git a/src/docbkx/reference/programming-model/introducedmethods.xml b/src/docbkx/reference/programming-model/introducedmethods.xml index a212334e2..6ac8b04f9 100644 --- a/src/docbkx/reference/programming-model/introducedmethods.xml +++ b/src/docbkx/reference/programming-model/introducedmethods.xml @@ -114,19 +114,19 @@ - Executes the given query, replacing the first %d with the node-id and returning the results converted to the target type. + Executes the given query, replacing %start with the node-id and returning the results converted to the target type. <T> Iterable<T> NodeBacked.findAllByQuery(final String query, final Class<T> targetType) - Executes the given query, replacing the first %d with the node-id and returning the original result, but with nodes and relationships replaced by their appropriate entities. + Executes the given query, replacing %start with the node-id and returning the original result, but with nodes and relationships replaced by their appropriate entities. Iterable<Map<String,Object>> NodeBacked.findAllByQuery(final String query) - Executes the given query, replacing the first %d with the node-id and returns a single result converted to the target type. + Executes the given query, replacing %start with the node-id and returns a single result converted to the target type. <T> T NodeBacked.findByQuery(final String query, final Class<T> targetType) diff --git a/src/docbkx/reference/programming-model/node-entities.xml b/src/docbkx/reference/programming-model/node-entities.xml index e4eb93ace..55acbc6ce 100644 --- a/src/docbkx/reference/programming-model/node-entities.xml +++ b/src/docbkx/reference/programming-model/node-entities.xml @@ -72,28 +72,33 @@ public class Movie {
- @GraphQuery: fields as query result views + @Query: fields as query result views - The @GraphQuery annotation leverages the delegation infrastructure used by the + The @Query annotation leverages the delegation infrastructure used by the Spring Data Graph aspects. It provides dynamic fields which, when accessed, return the values - selected by the provided query language expression. The provided query must contain a placeholder - for the id of the current entity start n=(%d) match n-[:FRIEND]->friend return friend - As graph queries can return variable number of entities the annotation can be put onto fields - with a single value, an Iterable of a type or an Iterable of Map<String,Object>. - The class of the resulting node entities must right now provided with the elementClass attribute. - Additional parameters are added to the query with Java's String.format substitution. + selected by the provided query language expression. The provided query must contain a placeholder named %start + for the id of the current entity. For instance start n=(%start) match n-[:FRIEND]->friend return friend. + Graph queries can return variable number of entities. That's why annotation can be put onto fields + with a single value, an Iterable of a concrete type or an Iterable of Map<String,Object>. + Additional parameters are taken from the params attribute of the @Query annotation. + The tuples form key-value pairs that are provided to the query at execution time. - @GraphQuery from a node entity + @Graph on a node entity field (friend) return friend", - elementClass = Person.class, params = "FRIEND") + @Query(value = "start n=(%start) match (n)-[:%relType]->(friend) return friend", + params = {"relType", "FRIEND"}) private Iterable friends; } ]]> + + + Please note that this annotation can also be used on repository methods. + +
@GraphTraversal: fields as traversal result views diff --git a/src/docbkx/reference/programming-model/repositories.xml b/src/docbkx/reference/programming-model/repositories.xml index d464b1ad9..1038c8abb 100644 --- a/src/docbkx/reference/programming-model/repositories.xml +++ b/src/docbkx/reference/programming-model/repositories.xml @@ -132,13 +132,16 @@
Annotated Queries - Queries for the graph-query language cypher can be supplied with the @GraphQuery annotation. - That means every method annotated with @GraphQuery("start n=(%d) match (n)-->(m) return m") - will use the query string. The String-format parameters are replaced by the actual method parameters in order, - whereby Node and Relationship-Entities are resolved to their respective id's and all other parameters are + Queries for the cypher graph-query language can be supplied with the @Query annotation. + That means every method annotated with @Query("start n=(%node) match (n)-->(m) return m") + will use the query string. The named parameter %node will be replaced by the actual method parameters. + Node and Relationship-Entities are resolved to their respective id's and all other parameters are replaced directly (i.e. Strings, Longs, etc). There is special support for the Sort and Pageable parameters from Spring Data Commons, which are supported to add programmatic paging and sorting (alternatively static paging and sorting can be supplied in the query string itself). + + For using the named parameters you have to either annotate the parameters of the method with the + @Param("node") annotation or enable debug symbols.
@@ -146,8 +149,9 @@ Named Queries Spring Data Graph also supports the notion of named queries which are externalized in property-config-files (META-INF/graph-named-queries.properties). Those files have the format: - Entity.finderName=query (e.g. Person.findBoss=start p=(%d) match (p)<-[:BOSS]-(boss) return boss). - Otherwise named queries support the same parameters as annotated queries. + Entity.finderName=query (e.g. Person.findBoss=start p=(%person) match (p)<-[:BOSS]-(boss) return boss). + Otherwise named queries support the same parameters as annotated queries. For using the named parameters you have to either + annotate the parameters of the method with the @Param("person") annotation or enable debug symbols.