Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@Query Result type is not Set. [DATAGRAPH-474] #1037

Closed
spring-projects-issues opened this issue May 12, 2014 · 6 comments
Closed

@Query Result type is not Set. [DATAGRAPH-474] #1037

spring-projects-issues opened this issue May 12, 2014 · 6 comments

Comments

@spring-projects-issues
Copy link

@spring-projects-issues spring-projects-issues commented May 12, 2014

kim jejun opened DATAGRAPH-474 and commented

I use this code in my domain class and I expect sortedComments type is Set.
but result type is SpringEndResult.

How can i use this? in my jsp view or java code?
Is it right result?

plz see reference url.

thanks.

@Query(value = "START a=node({self}) MATCH (a)<-[:`COMMENT_TO`]-(b) RETURN b ORDER BY    b.createdAt DESC")
private Set<BaseComment> sortedComments;

Affects: 3.0 GA (Codd)

Reference URL: http://stackoverflow.com/questions/23555090/how-can-i-use-query-result-in-sdn3

Referenced from: commits f590399

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented May 13, 2014

Duncan Brown commented

I tried something very similar with the latest SDN code and annotated the Person @NodeEntity POJO with a similar @Query (just changed the method name and return type from Iterable to a Set). I.e. it was this:

@Query("start person=node({self}) match (person)<-[:persons]-(team)-[:persons]->(member) return member")
private Set<Person> otherTeamMembersSet;

(As a side note: I was able to get back a result only if I didn't use the "transient" keyword, in spite of instructions to the contrary in the Person class. Am I missing something? Or is this just part of lazy loading and a template.fetch call needs to be made?)

I then tried calling this:

Set<Person> setPerson = boss.getOtherTeamMembersSet();

...where "boss" is a valid Person object.

Upon inspecting "setPerson", I can see that it thinks it's a "LinkedHashMap" (upon mousing over it); however, the "toString" actually thinks it's a conversion.QueryResultBuilder.

If I then try to iterate through the Set in ANY, I get a ClassCastException similar to the OP's; e.g.

java.lang.ClassCastException: org.springframework.data.neo4j.conversion.QueryResultBuilder cannot be cast to org.springframework.data.neo4j.model.Person

I'll see if I can't dig deeper, but hopefully this will be useful info for someone.

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented May 14, 2014

Duncan Brown commented

From above, because the Set is actually a LinkedHashSet with a "map" member (LinkedHashMap), any call to .iterator() returns the map's keySet iterator. The "key" currently happens to be a QueryResultBuilder, which naturally cannot be cast into some other @NodeEntity type by default.

QueryResultBuilder implements Iterable from Result, and so calling .iterator() from an Iterable<T> return type will work as expected. If we use the Set<T> version instead, then we're left with the LinkedHashSet with QRB objects inside.

When Spring goes to convert the value(s) into a Set (via org.springframework.core.convert.support.ObjectToCollectionConverter), a LinkedHashSet is created and the QRB(s) are added directly to the LHS, so changing things here sounds unlikely.

This should be enough info to make a decision in terms of an approach to take, though it's unlikely to be easy as the Set implementations all have that additional "map" abstraction inside. I might take a stab at figuring out one out if time allows

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented May 14, 2014

Duncan Brown commented

Sorry if this is obvious to you guys, but, the real offending lines mentioned above are these:

Collection<Object> target = CollectionFactory.createCollection(targetType.getType(), 1);
if (targetType.getElementTypeDescriptor() == null || targetType.getElementTypeDescriptor().isCollection()) {
target.add(source);
}

However, having a look at how SDN's repo methods work with @Query, it's done differently and it works, making use of Neo4j's IteratorUtil.addToCollection.

Does it make any sense to override/implement SDN's own default conversion service? Or is there a better technique?

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Jun 6, 2014

Michael Hunger commented

I think you have to use @Fetch with that field if you want it to be loaded eagerly.

Also sorting and a set don't really go well along. We should probably change the used Set implementation to a LinkedHashSet which retains the order. (Brad Nussbaum could you have a look? Should be in either QueryFieldAccessor or in QueryResultBuilder.to(Set.class)

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Sep 27, 2014

Aldray Low commented

Hi can i check if this issue is resolved? I am experiencing the same problem using neo4j 2.1.2 with spring-data-aspect 3.1.4-release.

The issue is when i need to use @Query with "...order asc|desc" inside the Domain class to retrieve sorted list of objects. Originally, i was using @Fetch and @RelatedTo but this doesn't fulfill my requirement of returning a sorted list.

I know this feature is working for Repository but implementing this way is going to make the whole code messy.

Appreciate if someone can help

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Nov 11, 2014

Michael Hunger commented

Using LinkedHashSet now.

The Set creation should be handled correctly now as part of QueryResultBuilder.as(Container)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant