DATAGRAPH-352/330 : Fixed issues relating to Sorting and Paging

This commit is contained in:
Nicki Watt
2013-07-09 16:21:47 +01:00
parent 4c74f979bb
commit ac3fcc4190
4 changed files with 122 additions and 13 deletions

View File

@@ -34,6 +34,7 @@ import org.springframework.data.neo4j.annotation.QueryType;
import org.springframework.data.neo4j.conversion.EndResult;
import org.springframework.data.neo4j.conversion.Result;
import org.springframework.data.neo4j.mapping.Neo4jPersistentProperty;
import org.springframework.data.neo4j.repository.query.CypherQuery;
import org.springframework.data.neo4j.support.Neo4jTemplate;
import org.springframework.data.neo4j.support.index.NoSuchIndexException;
import org.springframework.data.neo4j.support.index.NullReadableIndex;
@@ -346,7 +347,8 @@ public abstract class AbstractGraphRepository<S extends PropertyContainer, T> im
@Override
public EndResult<T> findAll(Sort sort) {
return findAll(); // todo
CypherQuery cq = new CypherQuery(template.getEntityType(clazz).getEntity(),template);
return query(cq.toQueryString(sort), Collections.EMPTY_MAP);
}
@Override

View File

@@ -25,6 +25,7 @@ import org.springframework.data.repository.query.Parameter;
import org.springframework.data.repository.query.parser.Part;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -91,6 +92,26 @@ public class CypherQuery implements CypherQueryDefinition {
return this;
}
private Sort getCypherEntityRefAwareSort(Sort sorts) {
List<Sort.Order> entityAwareOrders = new ArrayList<Sort.Order>();
Iterator<Sort.Order> i = sorts.iterator();
while( i.hasNext()) {
Sort.Order o = i.next();
entityAwareOrders.add( getEntityAwareOrderRef(o) );
}
Sort entityAwareSort = new Sort(entityAwareOrders);
return entityAwareSort;
}
private Sort.Order getEntityAwareOrderRef(Sort.Order o) {
// Cater for cases which cause 80% of the reported grief, i.e. assumes a string
// with no period refers to a property on entity - however this will
// not always be the case .. confirm with Michael ..
return (o.getProperty().contains("."))
? o
: new Sort.Order(o.getDirection(),getEntityName(entity)+"."+o.getProperty());
}
private boolean addedStartClause(PartInfo partInfo) {
if (!partInfo.isIndexed()) return false;
for (StartClause startClause : startClauses) {
@@ -192,8 +213,15 @@ public class CypherQuery implements CypherQueryDefinition {
@Override
public String toQueryString(Sort sort) {
return toQueryString(sort,true);
}
private String toQueryString(Sort sort,boolean applyMissingRefs) {
StringBuilder builder = new StringBuilder(render());
if (sort != null) builder.append(addSorts(sort));
if (sort != null) {
builder.append(addSorts(
applyMissingRefs ? getCypherEntityRefAwareSort(sort) : sort));
}
return builder.toString();
}

View File

@@ -20,10 +20,12 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Transaction;
import org.neo4j.helpers.collection.IteratorUtil;
import org.neo4j.test.ImpermanentGraphDatabase;
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.config.EnableNeo4jRepositories;
import org.springframework.data.neo4j.config.Neo4jConfiguration;
@@ -31,14 +33,17 @@ import org.springframework.data.neo4j.support.Neo4jTemplate;
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.HashSet;
import java.util.Set;
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;
@@ -130,6 +135,12 @@ interface RecipeRepository extends GraphRepository<Recipe> {
Set<Recipe> findByIngredient(Ingredient ingredient);
Iterable<Recipe> findByIngredient(Ingredient ingredient, Sort sort);
Iterable<Recipe> findByIngredientOrderByAuthorAsc(Ingredient ingredient);
Iterable<Recipe> findByIngredientOrderByAuthorDesc(Ingredient ingredient);
Set<Recipe> findBySecret(Ingredient ingredient);
Set<Recipe> findByIngredientAndAuthor(Ingredient ingredient, String author);
@@ -171,11 +182,11 @@ public class DerivedFinderTests {
@Autowired
private DishRepository dishRepository;
private Ingredient fish, spice, oliveOil, pear;
private Ingredient fish, spice, oliveOil, pear, chocolate;
private CookBook nakedChef, baking101;
private Recipe focaccia;
private Recipe focaccia, chocolateFudgeCake, whiteChocolateSquares;
@Before
public void setUp() throws Exception {
@@ -185,6 +196,7 @@ public class DerivedFinderTests {
Transaction transaction = graphDatabaseService.beginTx();
try {
chocolate = ingredientRepository.save(new Ingredient("chocolate"));
fish = ingredientRepository.save(new Ingredient("fish"));
spice = ingredientRepository.save(new Ingredient("spice x"));
oliveOil = ingredientRepository.save(new Ingredient("olive oil"));
@@ -196,6 +208,10 @@ public class DerivedFinderTests {
recipeRepository.save(new Recipe("The Colonel", "fried chicken", null, spice, null));
recipeRepository.save(new Recipe("Jamie", "pesto", oliveOil, null, nakedChef));
focaccia = recipeRepository.save(new Recipe("Hugh", "focaccia", oliveOil, null, baking101));
chocolateFudgeCake = recipeRepository.save(new Recipe("Nigella", "Chocolate Fudge cake", chocolate, null, null));
whiteChocolateSquares = recipeRepository.save(new Recipe("Heston", "White Chocolate squares", chocolate, null, null));
dish = dishRepository.save(new Dish(100));
transaction.success();
} finally {
@@ -288,4 +304,33 @@ public class DerivedFinderTests {
assertThat(foundDish.number, is(equalTo(dish.number)));
}
@Test
public void shouldFindCorrectlyOrderedUsingMethodSignatureAscending() {
Iterable<Recipe> recipes = recipeRepository.findByIngredientOrderByAuthorAsc(chocolate);
List<Recipe> recs = (List<Recipe>)asCollection(recipes);
assertThat( recs.size(), equalTo(2));
assertEquals("Heston" , recs.get(0).author);
assertEquals("Nigella" , recs.get(1).author);
}
@Test
public void shouldFindCorrectlyOrderedUsingMethodSignatureDescending() {
Iterable<Recipe> recipes = recipeRepository.findByIngredientOrderByAuthorDesc(chocolate);
List<Recipe> recs = (List<Recipe>)asCollection(recipes);
assertThat( recs.size(), equalTo(2));
assertEquals("Nigella" , recs.get(0).author);
assertEquals("Heston" , recs.get(1).author);
}
@Test
public void shouldFindCorrectlyOrderedUsingSortParam() {
Sort.Order order = new Sort.Order(Sort.Direction.DESC,"author");
Sort sort = new Sort(order);
Iterable<Recipe> recipes = recipeRepository.findByIngredient(chocolate, sort);
List<Recipe> recs = (List<Recipe>)asCollection(recipes);
assertThat( recs.size(), equalTo(2));
assertEquals("Nigella" , recs.get(0).author);
assertEquals("Heston" , recs.get(1).author);
}
}

View File

@@ -17,15 +17,10 @@
package org.springframework.data.neo4j.repository;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.neo4j.cypher.ExecutionEngine;
import org.neo4j.cypher.ExecutionResult;
import org.neo4j.graphdb.DynamicRelationshipType;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Transaction;
import org.neo4j.helpers.collection.IteratorUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -51,7 +46,10 @@ import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import java.util.*;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
@@ -146,7 +144,43 @@ public class GraphRepositoryTests {
assertThat(personRepository.exists(testTeam.michael.getId()), is(false));
}
@Test @Transactional
@Test
public void findAll() {
Iterable<Person> allPersons = personRepository.findAll();
assertThat(asCollection(allPersons), hasItems(testTeam.michael, testTeam.david, testTeam.emil));
}
@Test
public void findAllSortedAscending() {
Sort sort = new Sort(Sort.Direction.ASC, "name");
Iterable<Person> allPersons = personRepository.findAll(sort);
assertEquals(asList(testTeam.david, testTeam.emil, testTeam.michael), asCollection(allPersons));
}
@Test
public void findAllSortedDescending() {
Sort sort = new Sort(Sort.Direction.DESC, "name");
Iterable<Person> allPersons = personRepository.findAll(sort);
assertEquals(asList(testTeam.michael, testTeam.emil, testTeam.david), asCollection(allPersons));
}
@Test
public void findAllPageableWithSortDescending() {
Sort sort = new Sort(Sort.Direction.DESC, "name");
PageRequest page1Request = new PageRequest(0, 1, sort);
PageRequest page2Request = new PageRequest(1, 1, sort);
PageRequest page3Request = new PageRequest(2, 1, sort);
Iterable<Person> page1Result = personRepository.findAll(page1Request);
Iterable<Person> page2Result = personRepository.findAll(page2Request);
Iterable<Person> page3Result = personRepository.findAll(page3Request);
assertEquals (asList(testTeam.michael), asCollection(page1Result));
assertEquals (asList(testTeam.emil), asCollection(page2Result));
assertEquals (asList(testTeam.david), asCollection(page3Result));
}
@Test @Transactional
public void testFindIterableOfPersonWithQueryAnnotation() {
Iterable<Person> teamMembers = personRepository.findAllTeamMembers(testTeam.sdg);
assertThat( asCollection( teamMembers ), hasItems( testTeam.michael, testTeam.david, testTeam.emil ) );