DATAGRAPH-466 - Derived finders issue. Following feedback from @jexp. Changed TreeSet to LinkedHashSet to maintain query insertion order instead of how I'd originally implemented it where the order would be the same, irrespective of insertion order.
This commit is contained in:
@@ -15,6 +15,18 @@
|
||||
*/
|
||||
package org.springframework.data.neo4j.repository.query;
|
||||
|
||||
import static org.springframework.util.StringUtils.collectionToCommaDelimitedString;
|
||||
import static org.springframework.util.StringUtils.collectionToDelimitedString;
|
||||
import static org.springframework.util.StringUtils.hasText;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.mapping.context.PersistentPropertyPath;
|
||||
@@ -24,11 +36,6 @@ import org.springframework.data.neo4j.support.Neo4jTemplate;
|
||||
import org.springframework.data.repository.query.Parameter;
|
||||
import org.springframework.data.repository.query.parser.Part;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static org.springframework.util.StringUtils.*;
|
||||
import static org.springframework.util.StringUtils.hasText;
|
||||
|
||||
public class CypherQuery implements CypherQueryDefinition {
|
||||
private final VariableContext variableContext = new VariableContext();
|
||||
private final List<MatchClause> matchClauses = new ArrayList<MatchClause>();
|
||||
@@ -280,7 +287,8 @@ public class CypherQuery implements CypherQueryDefinition {
|
||||
}
|
||||
|
||||
private String toQueryString(List<MatchClause> matchClauses) {
|
||||
List<String> result = new ArrayList<String>(matchClauses.size());
|
||||
// Use a TreeSet to remove duplicate match clauses and maintain their order
|
||||
Set<String> result = new LinkedHashSet<String>();
|
||||
for (MatchClause matchClause : matchClauses) {
|
||||
result.add(matchClause.toString(variableContext));
|
||||
}
|
||||
|
||||
@@ -15,41 +15,44 @@
|
||||
*/
|
||||
package org.springframework.data.neo4j.repository;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.neo4j.graphdb.Direction.INCOMING;
|
||||
import static org.neo4j.graphdb.Direction.OUTGOING;
|
||||
import static org.neo4j.helpers.collection.IteratorUtil.asCollection;
|
||||
import static org.neo4j.helpers.collection.IteratorUtil.single;
|
||||
import static org.springframework.data.neo4j.SetHelper.asSet;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.neo4j.graphdb.GraphDatabaseService;
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.neo4j.graphdb.Transaction;
|
||||
import org.neo4j.helpers.collection.IteratorUtil;
|
||||
import org.neo4j.test.TestGraphDatabaseFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.neo4j.annotation.*;
|
||||
import org.springframework.data.neo4j.annotation.Fetch;
|
||||
import org.springframework.data.neo4j.annotation.GraphId;
|
||||
import org.springframework.data.neo4j.annotation.Indexed;
|
||||
import org.springframework.data.neo4j.annotation.NodeEntity;
|
||||
import org.springframework.data.neo4j.annotation.RelatedTo;
|
||||
import org.springframework.data.neo4j.config.EnableNeo4jRepositories;
|
||||
import org.springframework.data.neo4j.config.Neo4jConfiguration;
|
||||
import org.springframework.data.neo4j.support.Neo4jTemplate;
|
||||
import org.springframework.data.neo4j.support.index.IndexType;
|
||||
import org.springframework.data.neo4j.support.node.Neo4jHelper;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.neo4j.graphdb.Direction.INCOMING;
|
||||
import static org.neo4j.helpers.collection.IteratorUtil.asCollection;
|
||||
import static org.neo4j.helpers.collection.IteratorUtil.single;
|
||||
import static org.springframework.data.neo4j.SetHelper.asSet;
|
||||
|
||||
@NodeEntity
|
||||
class Ingredient {
|
||||
@@ -93,6 +96,9 @@ class CookBook {
|
||||
CookBook(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
@RelatedTo(type="HAS_RECIPE", direction = OUTGOING)
|
||||
Set<Recipe> recipes;
|
||||
}
|
||||
|
||||
@NodeEntity
|
||||
@@ -105,6 +111,7 @@ class Recipe {
|
||||
@Fetch
|
||||
Ingredient ingredient;
|
||||
|
||||
@RelatedTo(type="HAS_RECIPE", direction = INCOMING)
|
||||
CookBook cookBook;
|
||||
|
||||
@RelatedTo(direction = INCOMING)
|
||||
@@ -130,6 +137,13 @@ interface DishRepository extends GraphRepository<Dish> {
|
||||
Dish findByNumber(int number);
|
||||
}
|
||||
|
||||
interface CookBookRepository extends GraphRepository<CookBook> {
|
||||
CookBook findByTitle(String title);
|
||||
Set<CookBook> findByRecipesAuthor(String recipeAuthor);
|
||||
Set<CookBook> findByRecipesTitle(String recipeTitle);
|
||||
Set<CookBook> findByRecipesAuthorAndRecipesTitle(String recipeAuthor, String recipeTitle);
|
||||
}
|
||||
|
||||
interface RecipeRepository extends GraphRepository<Recipe> {
|
||||
Set<Recipe> findById(long id);
|
||||
|
||||
@@ -198,6 +212,9 @@ public class DerivedFinderTests {
|
||||
|
||||
@Autowired
|
||||
private DishRepository dishRepository;
|
||||
|
||||
@Autowired
|
||||
private CookBookRepository cookBookRepository;
|
||||
|
||||
private Ingredient fish, spice, oliveOil, pear, chocolate;
|
||||
|
||||
@@ -399,4 +416,28 @@ public class DerivedFinderTests {
|
||||
assertEquals("Nigella" , recs.get(0).author);
|
||||
assertEquals("Heston" , recs.get(1).author);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldFindByMultipleRelatedProperties() {
|
||||
Set<Recipe> jamieR = recipeRepository.findByAuthor("Jamie");
|
||||
assertThat(jamieR.size(), equalTo(1));
|
||||
|
||||
CookBook book = cookBookRepository.findByTitle("Naked Chef");
|
||||
assertThat(book, notNullValue());
|
||||
|
||||
// Ensure we can find the book via the recipe author
|
||||
Set<CookBook> books = cookBookRepository.findByRecipesAuthor("Jamie");
|
||||
assertThat(books.size(), equalTo(1));
|
||||
assertThat(books.iterator().next().title, equalTo("Naked Chef"));
|
||||
|
||||
// Ensure we can find the book via the recipe title
|
||||
books = cookBookRepository.findByRecipesTitle("pesto");
|
||||
assertThat(books.size(), equalTo(1));
|
||||
assertThat(books.iterator().next().title, equalTo("Naked Chef"));
|
||||
|
||||
// Now try to find the book via both the recipe author and the recipe title
|
||||
books = cookBookRepository.findByRecipesAuthorAndRecipesTitle("Jamie", "pesto");
|
||||
assertThat(books.size(), equalTo(1));
|
||||
assertThat(books.iterator().next().title, equalTo("Naked Chef"));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user