Skip to content

Commit 794b026

Browse files
committed
DATAMONGO-1979 - Polishing.
Rename QueryUtils method to decorateSort(…) to reflect the nature of the method. Add missing generics. Convert ReactiveMongoRepositoryTests to AssertJ. Add missing verifyComplete() steps to StepVerifier. Slight tweaks to Javadoc and reference docs. Original pull request: #566.
1 parent 8f11916 commit 794b026

File tree

9 files changed

+43
-40
lines changed

9 files changed

+43
-40
lines changed

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Query.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,14 +80,14 @@
8080

8181
/**
8282
* Defines a default sort order for the given query.<br />
83-
* <strong>NOTE</strong> The so set defaults can be altered / overwritten via an explicit
83+
* <strong>NOTE:</strong> The so set defaults can be altered / overwritten using an explicit
8484
* {@link org.springframework.data.domain.Sort} argument of the query method.
8585
*
8686
* <pre>
8787
* <code>
88-
*
88+
*
8989
* &#64;Query(sort = "{ age : -1 }") // order by age descending
90-
* List<Person> findByFirstname(String firstname);
90+
* List<Person> findByFirstname(String firstname);
9191
* </code>
9292
* </pre>
9393
*

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractMongoQuery.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ Query applyAnnotatedDefaultSortIfPresent(Query query) {
151151
return query;
152152
}
153153

154-
return QueryUtils.sneakInDefaultSort(query, Document.parse(method.getAnnotatedSort()));
154+
return QueryUtils.decorateSort(query, Document.parse(method.getAnnotatedSort()));
155155
}
156156

157157
/**

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractReactiveMongoQuery.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ Query applyAnnotatedDefaultSortIfPresent(Query query) {
193193
return query;
194194
}
195195

196-
return QueryUtils.sneakInDefaultSort(query, Document.parse(method.getAnnotatedSort()));
196+
return QueryUtils.decorateSort(query, Document.parse(method.getAnnotatedSort()));
197197
}
198198

199199
/**

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryMethod.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ public MongoQueryMethod(Method method, RepositoryMetadata metadata, ProjectionFa
8080

8181
this.method = method;
8282
this.mappingContext = mappingContext;
83-
this.annotationCache = new ConcurrentReferenceHashMap();
83+
this.annotationCache = new ConcurrentReferenceHashMap<>();
8484
}
8585

8686
/*
@@ -124,6 +124,7 @@ private Optional<String> findAnnotatedQuery() {
124124
*
125125
* @return
126126
*/
127+
@Nullable
127128
String getFieldSpecification() {
128129

129130
return lookupQueryAnnotation() //
@@ -159,7 +160,7 @@ public MongoEntityMetadata<?> getEntityInformation() {
159160
MongoPersistentEntity<?> collectionEntity = domainClass.isAssignableFrom(returnedObjectType) ? returnedEntity
160161
: managedEntity;
161162

162-
this.metadata = new SimpleMongoEntityMetadata<Object>((Class<Object>) returnedEntity.getType(),
163+
this.metadata = new SimpleMongoEntityMetadata<>((Class<Object>) returnedEntity.getType(),
163164
collectionEntity);
164165
}
165166
}
@@ -315,9 +316,10 @@ public String getAnnotatedSort() {
315316
"Expected to find @Query annotation but did not. Make sure to check hasAnnotatedSort() before."));
316317
}
317318

319+
@SuppressWarnings("unchecked")
318320
private <A extends Annotation> Optional<A> doFindAnnotation(Class<A> annotationType) {
319321

320-
return (Optional) this.annotationCache.computeIfAbsent(annotationType,
322+
return (Optional<A>) this.annotationCache.computeIfAbsent(annotationType,
321323
it -> Optional.ofNullable(AnnotatedElementUtils.findMergedAnnotation(method, it)));
322324
}
323325
}

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/QueryUtils.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,14 @@
3131
class QueryUtils {
3232

3333
/**
34-
* Add a default sort expression to the given Query. Attributes of the given {@code sort} may be overwritten by the
35-
* sort explicitly defined by the {@link Query} itself.
34+
* Decorate {@link Query} and add a default sort expression to the given {@link Query}. Attributes of the given
35+
* {@code sort} may be overwritten by the sort explicitly defined by the {@link Query} itself.
3636
*
3737
* @param query the {@link Query} to decorate.
3838
* @param defaultSort the default sort expression to apply to the query.
3939
* @return the query having the given {@code sort} applied.
4040
*/
41-
static Query sneakInDefaultSort(Query query, Document defaultSort) {
41+
static Query decorateSort(Query query, Document defaultSort) {
4242

4343
if (defaultSort.isEmpty()) {
4444
return query;

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveMongoQueryMethod.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ public ReactiveMongoQueryMethod(Method method, RepositoryMetadata metadata, Proj
7979
ClassUtils.getShortName(method.getDeclaringClass()), method.getName()));
8080
}
8181

82-
if (!multiWrapper && !singleWrapperWithWrappedPageableResult) {
82+
if (!multiWrapper) {
8383
throw new IllegalStateException(String.format(
8484
"Method has to use a either multi-item reactive wrapper return type or a wrapped Page/Slice type. Offending method: %s",
8585
method.toString()));

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ReactiveMongoRepositoryTests.java

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,11 @@
1515
*/
1616
package org.springframework.data.mongodb.repository;
1717

18-
import static org.hamcrest.Matchers.*;
19-
import static org.junit.Assert.*;
18+
import static org.assertj.core.api.Assertions.offset;
2019
import static org.springframework.data.domain.Sort.Direction.*;
20+
import static org.springframework.data.mongodb.test.util.Assertions.assertThat;
2121

2222
import lombok.NoArgsConstructor;
23-
import org.hamcrest.collection.IsIterableContainingInOrder;
24-
import org.springframework.data.domain.Sort.Direction;
2523
import reactor.core.Disposable;
2624
import reactor.core.publisher.Flux;
2725
import reactor.core.publisher.Mono;
@@ -45,6 +43,7 @@
4543
import org.springframework.data.domain.PageRequest;
4644
import org.springframework.data.domain.Pageable;
4745
import org.springframework.data.domain.Sort;
46+
import org.springframework.data.domain.Sort.Direction;
4847
import org.springframework.data.geo.Circle;
4948
import org.springframework.data.geo.Distance;
5049
import org.springframework.data.geo.GeoResult;
@@ -130,12 +129,12 @@ public void shouldFindByLastName() {
130129

131130
@Test // DATAMONGO-1444
132131
public void shouldFindOneByLastName() {
133-
StepVerifier.create(repository.findOneByLastname(carter.getLastname())).expectNext(carter);
132+
StepVerifier.create(repository.findOneByLastname(carter.getLastname())).expectNext(carter).verifyComplete();
134133
}
135134

136135
@Test // DATAMONGO-1444
137136
public void shouldFindOneByPublisherOfLastName() {
138-
StepVerifier.create(repository.findByLastname(Mono.just(carter.getLastname()))).expectNext(carter);
137+
StepVerifier.create(repository.findByLastname(Mono.just(carter.getLastname()))).expectNext(carter).verifyComplete();
139138
}
140139

141140
@Test // DATAMONGO-1444
@@ -164,6 +163,7 @@ public void shouldFindUsingPublishersInStringQuery() {
164163

165164
@Test // DATAMONGO-1444
166165
public void shouldFindByLastNameAndSort() {
166+
167167
StepVerifier.create(repository.findByLastname("Matthews", Sort.by(ASC, "age"))) //
168168
.expectNext(oliver, dave) //
169169
.verifyComplete();
@@ -188,11 +188,11 @@ public void shouldUseTailableCursor() throws Exception {
188188

189189
Disposable disposable = cappedRepository.findByKey("value").doOnNext(documents::add).subscribe();
190190

191-
assertThat(documents.poll(5, TimeUnit.SECONDS), is(notNullValue()));
191+
assertThat(documents.poll(5, TimeUnit.SECONDS)).isNotNull();
192192

193193
StepVerifier.create(template.insert(new Capped("value", Math.random()))).expectNextCount(1).verifyComplete();
194-
assertThat(documents.poll(5, TimeUnit.SECONDS), is(notNullValue()));
195-
assertThat(documents.isEmpty(), is(true));
194+
assertThat(documents.poll(5, TimeUnit.SECONDS)).isNotNull();
195+
assertThat(documents).isEmpty();
196196

197197
disposable.dispose();
198198
}
@@ -213,16 +213,16 @@ public void shouldUseTailableCursorWithProjection() throws Exception {
213213
Disposable disposable = cappedRepository.findProjectionByKey("value").doOnNext(documents::add).subscribe();
214214

215215
CappedProjection projection1 = documents.poll(5, TimeUnit.SECONDS);
216-
assertThat(projection1, is(notNullValue()));
217-
assertThat(projection1.getRandom(), is(not(0)));
216+
assertThat(projection1).isNotNull();
217+
assertThat(projection1.getRandom()).isNotEqualTo(0);
218218

219219
StepVerifier.create(template.insert(new Capped("value", Math.random()))).expectNextCount(1).verifyComplete();
220220

221221
CappedProjection projection2 = documents.poll(5, TimeUnit.SECONDS);
222-
assertThat(projection2, is(notNullValue()));
223-
assertThat(projection2.getRandom(), is(not(0)));
222+
assertThat(projection2).isNotNull();
223+
assertThat(projection2.getRandom()).isNotEqualTo(0);
224224

225-
assertThat(documents.isEmpty(), is(true));
225+
assertThat(documents).isEmpty();
226226

227227
disposable.dispose();
228228
}
@@ -263,8 +263,8 @@ public void findsPeopleGeoresultByLocationWithinBox() {
263263
new Distance(2000, Metrics.KILOMETERS)) //
264264
).consumeNextWith(actual -> {
265265

266-
assertThat(actual.getDistance().getValue(), is(closeTo(1, 1)));
267-
assertThat(actual.getContent(), is(equalTo(dave)));
266+
assertThat(actual.getDistance().getValue()).isCloseTo(1, offset(1d));
267+
assertThat(actual.getContent()).isEqualTo(dave);
268268
}).verifyComplete();
269269
}
270270

@@ -280,8 +280,8 @@ public void findsPeoplePageableGeoresultByLocationWithinBox() {
280280
PageRequest.of(0, 10))) //
281281
.consumeNextWith(actual -> {
282282

283-
assertThat(actual.getDistance().getValue(), is(closeTo(1, 1)));
284-
assertThat(actual.getContent(), is(equalTo(dave)));
283+
assertThat(actual.getDistance().getValue()).isCloseTo(1, offset(1d));
284+
assertThat(actual.getContent()).isEqualTo(dave);
285285
}).verifyComplete();
286286
}
287287

@@ -313,17 +313,17 @@ public void shouldReturnFirstFindFirstWithMoreResults() {
313313
public void findAppliesAnnotatedSort() {
314314

315315
repository.findByAgeGreaterThan(40).collectList().as(StepVerifier::create).consumeNextWith(result -> {
316-
assertThat(result, IsIterableContainingInOrder.contains(carter, boyd, dave, leroi));
317-
});
316+
assertThat(result).containsSequence(carter, boyd, dave, leroi);
317+
}).verifyComplete();
318318
}
319319

320320
@Test // DATAMONGO-1979
321321
public void findWithSortOverwritesAnnotatedSort() {
322322

323323
repository.findByAgeGreaterThan(40, Sort.by(Direction.ASC, "age")).collectList().as(StepVerifier::create)
324324
.consumeNextWith(result -> {
325-
assertThat(result, IsIterableContainingInOrder.contains(leroi, dave, boyd, carter));
326-
});
325+
assertThat(result).containsSequence(leroi, dave, boyd, carter);
326+
}).verifyComplete();
327327
}
328328

329329
interface ReactivePersonRepository extends ReactiveMongoRepository<Person, String> {

src/main/asciidoc/new-features.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
* Tailable cursors for imperative driver.
1414
* <<mongo.sessions, MongoDB 3.6 Session>> support for the imperative and reactive Template APIs.
1515
* <<mongo.transactions, MongoDB 4.0 Transaction>> support and a MongoDB-specific transaction manager implementation.
16+
* <<mongodb.repositories.queries.sort,Default sort specifications for repository query methods>> using `@Query(sort=…)`.
1617

1718
[[new-features.2-0-0]]
1819
== What's New in Spring Data MongoDB 2.0

src/main/asciidoc/reference/mongo-repositories.adoc

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -398,9 +398,9 @@ The query in the preceding example returns only the `firstname`, `lastname` and
398398
[[mongodb.repositories.queries.sort]]
399399
=== Sorting Query Method results
400400

401-
When it comes to sorting MongoDB query results via the repository interface there are several options as listed below.
401+
MongoDB repositories allow various approaches to define sorting order. Let's take a look at the following example:
402402

403-
.Sorting query results
403+
.Sorting Query Results
404404
====
405405
[source,java]
406406
----
@@ -417,10 +417,10 @@ public interface PersonRepository extends MongoRepository<Person, String> {
417417
List<Person> findByLastname(String lastname, Sort sort); <4>
418418
}
419419
----
420-
<1> Fixed sorting derived from method name. `SortByAgeDesc` results in `{ age : -1 }` sort parameter.
421-
<2> Dynamic sorting via method argument. `Sort.by(DESC, "age")` creates a `{ age : -1 }` sort parameter.
422-
<3> Fixed sorting via `Query` annotation. Sort parameter applied as stated in the `sort` attribute.
423-
<4> Default sorting via `Query` annotation combined with dynamic one via method argument. `Sort.unsorted()`
420+
<1> Static sorting derived from method name. `SortByAgeDesc` results in `{ age : -1 }` for the sort parameter.
421+
<2> Dynamic sorting using a method argument. `Sort.by(DESC, "age")` creates `{ age : -1 }` for the sort parameter.
422+
<3> Static sorting via `Query` annotation. Sort parameter applied as stated in the `sort` attribute.
423+
<4> Default sorting via `Query` annotation combined with dynamic one via a method argument. `Sort.unsorted()`
424424
results in `{ age : -1 }`. Using `Sort.by(ASC, "age")` overrides the defaults and creates `{ age : 1 }`. `Sort.by
425425
(ASC, "firstname")` alters the default and results in `{ age : -1, firstname : 1 }`.
426426
====

0 commit comments

Comments
 (0)