DATAGRAPH-352/330 : Fixed issues relating to Sorting and Paging
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 ) );
|
||||
|
||||
Reference in New Issue
Block a user