Skip to content

Commit f3d2ae3

Browse files
committedDec 18, 2014
DATAMONGO-1120 - Fix execution of query methods using pagination and field mapping customizations.
Repository queries that used pagination and referred to a field that was customized were failing as the count query executed was not mapped correctly in MongoOperations. This result from the fix for DATAMONGO-1080 which removed the premature field name translation from AbstractMongoQuery and thus lead to unmapped field names being used for the count query. We now expose the previously existing, but not public count(…) method on MongoOperations that takes both an entity type as well as an explicit collection name to be able to count-query a dedicated collection but still get the query mapping applied for a certain type. Related ticket: DATAMONGO-1080.
1 parent b6ecce3 commit f3d2ae3

File tree

5 files changed

+40
-27
lines changed

5 files changed

+40
-27
lines changed
 

‎spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -652,14 +652,28 @@ <T> T findAndModify(Query query, Update update, FindAndModifyOptions options, Cl
652652
long count(Query query, Class<?> entityClass);
653653

654654
/**
655-
* Returns the number of documents for the given {@link Query} querying the given collection.
655+
* Returns the number of documents for the given {@link Query} querying the given collection. The given {@link Query}
656+
* must solely consist of document field references as we lack type information to map potential property references
657+
* onto document fields. TO make sure the query gets mapped, use {@link #count(Query, Class, String)}.
656658
*
657659
* @param query
658660
* @param collectionName must not be {@literal null} or empty.
659661
* @return
662+
* @see #count(Query, Class, String)
660663
*/
661664
long count(Query query, String collectionName);
662665

666+
/**
667+
* Returns the number of documents for the given {@link Query} by querying the given collection using the given entity
668+
* class to map the given {@link Query}.
669+
*
670+
* @param query
671+
* @param entityClass must not be {@literal null}.
672+
* @param collectionName must not be {@literal null} or empty.
673+
* @return
674+
*/
675+
long count(Query query, Class<?> entityClass, String collectionName);
676+
663677
/**
664678
* Insert the object into the collection for the entity type of the object to save.
665679
* <p/>

‎spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,11 @@ public long count(final Query query, String collectionName) {
642642
return count(query, null, collectionName);
643643
}
644644

645-
private long count(Query query, Class<?> entityClass, String collectionName) {
645+
/*
646+
* (non-Javadoc)
647+
* @see org.springframework.data.mongodb.core.MongoOperations#count(org.springframework.data.mongodb.core.query.Query, java.lang.Class, java.lang.String)
648+
*/
649+
public long count(Query query, Class<?> entityClass, String collectionName) {
646650

647651
Assert.hasText(collectionName);
648652
final DBObject dbObject = query == null ? null : queryMapper.getMappedObject(query.getQueryObject(),

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -259,9 +259,11 @@ public PagedExecution(Pageable pageable) {
259259
Object execute(Query query) {
260260

261261
MongoEntityMetadata<?> metadata = method.getEntityInformation();
262+
String collectionName = metadata.getCollectionName();
263+
Class<?> type = metadata.getJavaType();
262264

263265
int overallLimit = query.getLimit();
264-
long count = operations.count(query, metadata.getCollectionName());
266+
long count = operations.count(query, type, collectionName);
265267
count = overallLimit != 0 ? Math.min(count, query.getLimit()) : count;
266268

267269
boolean pageableOutOfScope = pageable.getOffset() > count;
@@ -278,7 +280,7 @@ Object execute(Query query) {
278280
query.limit(overallLimit - pageable.getOffset());
279281
}
280282

281-
List<?> result = operations.find(query, metadata.getJavaType(), metadata.getCollectionName());
283+
List<?> result = operations.find(query, type, collectionName);
282284
return new PageImpl(result, pageable, count);
283285
}
284286
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.springframework.data.mongodb.core.index.Indexed;
2626
import org.springframework.data.mongodb.core.mapping.DBRef;
2727
import org.springframework.data.mongodb.core.mapping.Document;
28+
import org.springframework.data.mongodb.core.mapping.Field;
2829

2930
/**
3031
* Sample domain class.
@@ -50,7 +51,7 @@ public enum Sex {
5051

5152
@GeoSpatialIndexed private Point location;
5253

53-
private Address address;
54+
private @Field("add") Address address;
5455
private Set<Address> shippingAddresses;
5556

5657
@DBRef User creator;

‎spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/AbstractMongoQueryUnitTests.java

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

18-
import static org.hamcrest.CoreMatchers.*;
18+
import static org.hamcrest.Matchers.*;
1919
import static org.junit.Assert.*;
2020
import static org.mockito.Matchers.*;
2121
import static org.mockito.Mockito.*;
@@ -100,8 +100,7 @@ public void testDeleteExecutionCallsRemoveCorreclty() {
100100

101101
createQueryForMethod("deletePersonByLastname", String.class).setDeleteQuery(true).execute(new Object[] { "booh" });
102102

103-
verify(this.mongoOperationsMock, times(1)).remove(Matchers.any(Query.class), Matchers.eq(Person.class),
104-
Matchers.eq("persons"));
103+
verify(this.mongoOperationsMock, times(1)).remove(Matchers.any(Query.class), eq(Person.class), eq("persons"));
105104
verify(this.mongoOperationsMock, times(0)).find(Matchers.any(Query.class), Matchers.any(Class.class),
106105
Matchers.anyString());
107106
}
@@ -119,8 +118,8 @@ public void testDeleteExecutionLoadsListOfRemovedDocumentsWhenReturnTypeIsCollec
119118

120119
createQueryForMethod("deleteByLastname", String.class).setDeleteQuery(true).execute(new Object[] { "booh" });
121120

122-
verify(this.mongoOperationsMock, times(1)).findAllAndRemove(Matchers.any(Query.class), Matchers.eq(Person.class),
123-
Matchers.eq("persons"));
121+
verify(this.mongoOperationsMock, times(1)).findAllAndRemove(Matchers.any(Query.class), eq(Person.class),
122+
eq("persons"));
124123
}
125124

126125
/**
@@ -143,15 +142,14 @@ public void testDeleteExecutionReturnsZeroWhenWriteResultIsNull() {
143142
public void testDeleteExecutionReturnsNrDocumentsDeletedFromWriteResult() {
144143

145144
when(writeResultMock.getN()).thenReturn(100);
146-
when(this.mongoOperationsMock.remove(Matchers.any(Query.class), Matchers.eq(Person.class), Matchers.eq("persons")))
147-
.thenReturn(writeResultMock);
145+
when(this.mongoOperationsMock.remove(Matchers.any(Query.class), eq(Person.class), eq("persons"))).thenReturn(
146+
writeResultMock);
148147

149148
MongoQueryFake query = createQueryForMethod("deletePersonByLastname", String.class);
150149
query.setDeleteQuery(true);
151150

152151
assertThat(query.execute(new Object[] { "fake" }), is((Object) 100L));
153-
verify(this.mongoOperationsMock, times(1)).remove(Matchers.any(Query.class), Matchers.eq(Person.class),
154-
Matchers.eq("persons"));
152+
verify(this.mongoOperationsMock, times(1)).remove(Matchers.any(Query.class), eq(Person.class), eq("persons"));
155153
}
156154

157155
/**
@@ -165,8 +163,7 @@ public void metadataShouldNotBeAddedToQueryWhenNotPresent() {
165163

166164
ArgumentCaptor<Query> captor = ArgumentCaptor.forClass(Query.class);
167165

168-
verify(this.mongoOperationsMock, times(1))
169-
.find(captor.capture(), Matchers.eq(Person.class), Matchers.eq("persons"));
166+
verify(this.mongoOperationsMock, times(1)).find(captor.capture(), eq(Person.class), eq("persons"));
170167

171168
assertThat(captor.getValue().getMeta().getComment(), nullValue());
172169
}
@@ -182,8 +179,7 @@ public void metadataShouldBeAddedToQueryCorrectly() {
182179

183180
ArgumentCaptor<Query> captor = ArgumentCaptor.forClass(Query.class);
184181

185-
verify(this.mongoOperationsMock, times(1))
186-
.find(captor.capture(), Matchers.eq(Person.class), Matchers.eq("persons"));
182+
verify(this.mongoOperationsMock, times(1)).find(captor.capture(), eq(Person.class), eq("persons"));
187183
assertThat(captor.getValue().getMeta().getComment(), is("comment"));
188184
}
189185

@@ -198,7 +194,7 @@ public void metadataShouldBeAddedToCountQueryCorrectly() {
198194

199195
ArgumentCaptor<Query> captor = ArgumentCaptor.forClass(Query.class);
200196

201-
verify(this.mongoOperationsMock, times(1)).count(captor.capture(), Matchers.eq("persons"));
197+
verify(this.mongoOperationsMock, times(1)).count(captor.capture(), eq(Person.class), eq("persons"));
202198
assertThat(captor.getValue().getMeta().getComment(), is("comment"));
203199
}
204200

@@ -213,8 +209,7 @@ public void metadataShouldBeAddedToStringBasedQueryCorrectly() {
213209

214210
ArgumentCaptor<Query> captor = ArgumentCaptor.forClass(Query.class);
215211

216-
verify(this.mongoOperationsMock, times(1))
217-
.find(captor.capture(), Matchers.eq(Person.class), Matchers.eq("persons"));
212+
verify(this.mongoOperationsMock, times(1)).find(captor.capture(), eq(Person.class), eq("persons"));
218213
assertThat(captor.getValue().getMeta().getComment(), is("comment"));
219214
}
220215

@@ -233,8 +228,7 @@ public void slicedExecutionShouldRetainNrOfElementsToSkip() {
233228

234229
ArgumentCaptor<Query> captor = ArgumentCaptor.forClass(Query.class);
235230

236-
verify(this.mongoOperationsMock, times(2))
237-
.find(captor.capture(), Matchers.eq(Person.class), Matchers.eq("persons"));
231+
verify(this.mongoOperationsMock, times(2)).find(captor.capture(), eq(Person.class), eq("persons"));
238232

239233
assertThat(captor.getAllValues().get(0).getSkip(), is(0));
240234
assertThat(captor.getAllValues().get(1).getSkip(), is(10));
@@ -255,8 +249,7 @@ public void slicedExecutionShouldIncrementLimitByOne() {
255249

256250
ArgumentCaptor<Query> captor = ArgumentCaptor.forClass(Query.class);
257251

258-
verify(this.mongoOperationsMock, times(2))
259-
.find(captor.capture(), Matchers.eq(Person.class), Matchers.eq("persons"));
252+
verify(this.mongoOperationsMock, times(2)).find(captor.capture(), eq(Person.class), eq("persons"));
260253

261254
assertThat(captor.getAllValues().get(0).getLimit(), is(11));
262255
assertThat(captor.getAllValues().get(1).getLimit(), is(11));
@@ -277,8 +270,7 @@ public void slicedExecutionShouldRetainSort() {
277270

278271
ArgumentCaptor<Query> captor = ArgumentCaptor.forClass(Query.class);
279272

280-
verify(this.mongoOperationsMock, times(2))
281-
.find(captor.capture(), Matchers.eq(Person.class), Matchers.eq("persons"));
273+
verify(this.mongoOperationsMock, times(2)).find(captor.capture(), eq(Person.class), eq("persons"));
282274

283275
DBObject expectedSortObject = new BasicDBObjectBuilder().add("bar", -1).get();
284276
assertThat(captor.getAllValues().get(0).getSortObject(), is(expectedSortObject));

0 commit comments

Comments
 (0)
Please sign in to comment.