spring-projects / spring-data-neo4j

Provide support to increase developer productivity in Java when using Neo4j. Uses familiar Spring concepts such as a template classes for core API usage and lightweight repository style data access.
http://spring.io/projects/spring-data-neo4j
Apache License 2.0
825 stars 619 forks source link

Repository methods with Iterable<Entity> are not converted to proper query and end with exception [DATAGRAPH-507] #1069

Closed spring-projects-issues closed 7 years ago

spring-projects-issues commented 10 years ago

Martin Sivák opened DATAGRAPH-507 and commented

I have a repository with method:

// User extends UserGroup
@Query("START a=node({0}), t=node({1}) MATCH path=a -[:PROVIDE_MEMBERS*0..]-> t RETURN count(path) > 0")
Boolean checkMembershipInGroups(UserGroup member, Iterable<UserGroup> target);

And calling it with HashSet\ as the second argument ends up with the following exception:

userGroupRepository.checkMembershipInGroups(currentUser, d.getOpenFor());
// d.getOpenFor() returns Set<UserGroup> with a single element (NodeId 0).
org.springframework.dao.InvalidDataAccessResourceUsageException: Error executing statement START a=node({0}), t=node({1}) MATCH path=a -[:PROVIDE_MEMBERS*0..]-> t RETURN count(path) > 0; nested exception is org.springframework.dao.InvalidDataAccessResourceUsageException: Error executing statement START a=node({0}), t=node({1}) MATCH path=a -[:PROVIDE_MEMBERS*0..]-> t RETURN count(path) > 0; nested exception is scala.MatchError: cz.lkbrno05.entities.User@0 (of class cz.lkbrno05.entities.User)
    at org.springframework.data.neo4j.support.query.CypherQueryEngineImpl.query(CypherQueryEngineImpl.java:61)
    at org.springframework.data.neo4j.repository.query.GraphRepositoryQuery.dispatchQuery(GraphRepositoryQuery.java:117)
    at org.springframework.data.neo4j.repository.query.GraphRepositoryQuery$1.doWithGraph(GraphRepositoryQuery.java:88)
    at org.springframework.data.neo4j.support.Neo4jTemplate.doExecute(Neo4jTemplate.java:456)
    at org.springframework.data.neo4j.support.Neo4jTemplate.access$000(Neo4jTemplate.java:86)
    at org.springframework.data.neo4j.support.Neo4jTemplate$2.doInTransaction(Neo4jTemplate.java:470)
    at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133)
    at org.springframework.data.neo4j.support.Neo4jTemplate.exec(Neo4jTemplate.java:467)
    at org.springframework.data.neo4j.repository.query.GraphRepositoryQuery.execute(GraphRepositoryQuery.java:82)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:384)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:344)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:98)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:262)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
    at com.sun.proxy.$Proxy116.checkMembershipInGroups(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:201)
    at com.sun.proxy.$Proxy117.checkMembershipInGroups(Unknown Source)
    at cz.lkbrno05.webapp.controllers.DocumentController.getDocument(DocumentController.java:425)

I debugged the issue and it lies in org.springframework.data.neo4j.repository.query.GraphRepositoryQuery.convertGraphEntityToId which is supposed to convert entities to NodeIds. But it does not know how to process Iterables.

Everything worked properly when I converted my method to use Iterable\ and passed precomputed Set of NodeIds to it.

List<Long> openFor = new ArrayList<Long>();
for (UserGroup userGroup: d.getOpenFor()) {
    openFor.add(userGroup.getNodeId());
}

// Boolean checkMembershipInGroups(UserGroup member, Iterable<Long> target);
userGroupRepository.checkMembershipInGroups(currentUser, openFor);

Affects: 3.1 GA (Dijkstra), 3.1.4 (Dijkstra SR4)

spring-projects-issues commented 7 years ago

Nicolas Mervaillie commented

In order to give users a better vision of what’s happening on SDN, we are bulk closing several issues because they are no more relevant, or related to old and un-maintained SDN versions. We tried to keep the issues that are still relevant, like feature requests that are still absent from SDN. However, some may have been closed by error. If so, please feel free to reopen.