From 173a62b5ce3cc5e1c5ff2eb948c6367dc8ea19c9 Mon Sep 17 00:00:00 2001 From: Thomas Darimont Date: Tue, 4 Nov 2014 15:21:21 +0100 Subject: [PATCH] DATAMONGO-1085 - Fixed sorting with Querydsl in QueryDslMongoRepository. We now translate QSort's OrderSpecifiers into appropriate sort criteria. Previously the OrderSpecifiers were not correctly translated to appropriate property path expressions. We're now overriding support for findAll(Pageable) and findAll(Sort) to QueryDslMongoRepository to apply special QSort handling. Original pull request: #236. --- .../support/QueryDslMongoRepository.java | 53 +++++++++++-- ...tractPersonRepositoryIntegrationTests.java | 77 +++++++++++++++++++ 2 files changed, 122 insertions(+), 8 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QueryDslMongoRepository.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QueryDslMongoRepository.java index 35cf425eb..9aaddd2db 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QueryDslMongoRepository.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QueryDslMongoRepository.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2012 the original author or authors. + * Copyright 2011-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,6 +27,7 @@ import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.repository.query.MongoEntityInformation; import org.springframework.data.querydsl.EntityPathResolver; +import org.springframework.data.querydsl.QSort; import org.springframework.data.querydsl.QueryDslPredicateExecutor; import org.springframework.data.querydsl.SimpleEntityPathResolver; import org.springframework.data.repository.core.EntityInformation; @@ -44,6 +45,7 @@ import com.mysema.query.types.path.PathBuilder; * Special QueryDsl based repository implementation that allows execution {@link Predicate}s in various forms. * * @author Oliver Gierke + * @author Thomas Darimont */ public class QueryDslMongoRepository extends SimpleMongoRepository implements QueryDslPredicateExecutor { @@ -105,7 +107,6 @@ public class QueryDslMongoRepository extends SimpleM * @see org.springframework.data.querydsl.QueryDslPredicateExecutor#findAll(com.mysema.query.types.Predicate, com.mysema.query.types.OrderSpecifier[]) */ public List findAll(Predicate predicate, OrderSpecifier... orders) { - return createQueryFor(predicate).orderBy(orders).list(); } @@ -115,7 +116,7 @@ public class QueryDslMongoRepository extends SimpleM */ @Override public Iterable findAll(OrderSpecifier... orders) { - return createQueryFor(new Predicate[0]).orderBy(orders).list(); + return createQuery().orderBy(orders).list(); } /* @@ -130,6 +131,28 @@ public class QueryDslMongoRepository extends SimpleM return new PageImpl(applyPagination(query, pageable).list(), pageable, countQuery.count()); } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.repository.support.SimpleMongoRepository#findAll(org.springframework.data.domain.Pageable) + */ + @Override + public Page findAll(Pageable pageable) { + + MongodbQuery countQuery = createQuery(); + MongodbQuery query = createQuery(); + + return new PageImpl(applyPagination(query, pageable).list(), pageable, countQuery.count()); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.repository.support.SimpleMongoRepository#findAll(org.springframework.data.domain.Sort) + */ + @Override + public List findAll(Sort sort) { + return applySorting(createQuery(), sort).list(); + } + /* * (non-Javadoc) * @see org.springframework.data.querydsl.QueryDslPredicateExecutor#count(com.mysema.query.types.Predicate) @@ -144,12 +167,17 @@ public class QueryDslMongoRepository extends SimpleM * @param predicate * @return */ - private MongodbQuery createQueryFor(Predicate... predicate) { + private MongodbQuery createQueryFor(Predicate predicate) { + return createQuery().where(predicate); + } - Class domainType = entityInformation.getJavaType(); - - MongodbQuery query = new SpringDataMongodbQuery(mongoOperations, domainType); - return query.where(predicate); + /** + * Creates a {@link MongodbQuery}. + * + * @return + */ + private MongodbQuery createQuery() { + return new SpringDataMongodbQuery(mongoOperations, entityInformation.getJavaType()); } /** @@ -182,6 +210,15 @@ public class QueryDslMongoRepository extends SimpleM return query; } + // TODO: find better solution than instanceof check + if (sort instanceof QSort) { + + List> orderSpecifiers = ((QSort) sort).getOrderSpecifiers(); + query.orderBy(orderSpecifiers.toArray(new OrderSpecifier[orderSpecifiers.size()])); + + return query; + } + for (Order order : sort) { query.orderBy(toOrder(order)); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java index 8966c9a95..5423ad68c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java @@ -24,6 +24,7 @@ import java.util.Arrays; import java.util.HashSet; import java.util.List; +import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; @@ -47,6 +48,7 @@ import org.springframework.data.geo.Polygon; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.query.BasicQuery; import org.springframework.data.mongodb.repository.Person.Sex; +import org.springframework.data.querydsl.QSort; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** @@ -1071,4 +1073,79 @@ public abstract class AbstractPersonRepositoryIntegrationTests { assertThat(result, contains(alicia, boyd, carter, dave, leroi, oliver, stefan)); } + + /** + * @see DATAMONGO-1085 + */ + @Test + public void shouldSupportSortingByQueryDslOrderSpecifier() { + + repository.deleteAll(); + + List persons = new ArrayList(); + + for (int i = 0; i < 3; i++) { + Person person = new Person(String.format("Siggi %s", i), "Bar", 30); + person.setAddress(new Address(String.format("Street %s", i), "12345", "SinCity")); + persons.add(person); + } + + repository.save(persons); + + QPerson person = QPerson.person; + + Iterable result = repository.findAll(person.firstname.isNotNull(), person.address.street.desc()); + + assertThat(result, is(Matchers. iterableWithSize(persons.size()))); + assertThat(result.iterator().next().getFirstname(), is(persons.get(2).getFirstname())); + } + + /** + * @see DATAMONGO-1085 + */ + @Test + public void shouldSupportSortingWithQSortByQueryDslOrderSpecifier() throws Exception { + + repository.deleteAll(); + + List persons = new ArrayList(); + + for (int i = 0; i < 3; i++) { + Person person = new Person(String.format("Siggi %s", i), "Bar", 30); + person.setAddress(new Address(String.format("Street %s", i), "12345", "SinCity")); + persons.add(person); + } + + repository.save(persons); + + PageRequest pageRequest = new PageRequest(0, 2, new QSort(person.address.street.desc())); + Iterable result = repository.findAll(pageRequest); + + assertThat(result, is(Matchers. iterableWithSize(2))); + assertThat(result.iterator().next().getFirstname(), is("Siggi 2")); + } + + /** + * @see DATAMONGO-1085 + */ + @Test + public void shouldSupportSortingWithQSort() throws Exception { + + repository.deleteAll(); + + List persons = new ArrayList(); + + for (int i = 0; i < 3; i++) { + Person person = new Person(String.format("Siggi %s", i), "Bar", 30); + person.setAddress(new Address(String.format("Street %s", i), "12345", "SinCity")); + persons.add(person); + } + + repository.save(persons); + + Iterable result = repository.findAll(new QSort(person.address.street.desc())); + + assertThat(result, is(Matchers. iterableWithSize(persons.size()))); + assertThat(result.iterator().next().getFirstname(), is("Siggi 2")); + } }