diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java index eb12ef577..4037f4650 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java @@ -115,6 +115,7 @@ import com.mongodb.WriteConcern; import com.mongodb.WriteResult; import com.mongodb.util.JSON; import com.mongodb.util.JSONParseException; + /** * Primary implementation of {@link MongoOperations}. * @@ -354,7 +355,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { } public void executeQuery(Query query, String collectionName, DocumentCallbackHandler dch) { - executeQuery(query, collectionName, dch, new QueryCursorPreparer(query)); + executeQuery(query, collectionName, dch, new QueryCursorPreparer(query, null)); } /** @@ -532,7 +533,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { } return doFind(collectionName, query.getQueryObject(), query.getFieldsObject(), entityClass, - new QueryCursorPreparer(query)); + new QueryCursorPreparer(query, entityClass)); } public T findById(Object id, Class entityClass) { @@ -614,8 +615,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { public T findAndModify(Query query, Update update, FindAndModifyOptions options, Class entityClass, String collectionName) { - return doFindAndModify(collectionName, query.getQueryObject(), query.getFieldsObject(), query.getSortObject(), - entityClass, update, options); + return doFindAndModify(collectionName, query.getQueryObject(), query.getFieldsObject(), + getMappedSortObject(query, entityClass), entityClass, update, options); } // Find methods that take a Query to express the query and that return a single object that is also removed from the @@ -626,8 +627,9 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { } public T findAndRemove(Query query, Class entityClass, String collectionName) { - return doFindAndRemove(collectionName, query.getQueryObject(), query.getFieldsObject(), query.getSortObject(), - entityClass); + + return doFindAndRemove(collectionName, query.getQueryObject(), query.getFieldsObject(), + getMappedSortObject(query, entityClass), entityClass); } public long count(Query query, Class entityClass) { @@ -1941,6 +1943,16 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { return converter; } + private DBObject getMappedSortObject(Query query, Class type) { + + if (query == null || query.getSortObject() == null) { + return null; + } + + MongoPersistentEntity entity = mappingContext.getPersistentEntity(type); + return queryMapper.getMappedObject(query.getSortObject(), entity); + } + // Callback implementations /** @@ -2134,9 +2146,12 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { class QueryCursorPreparer implements CursorPreparer { private final Query query; + private final Class type; + + public QueryCursorPreparer(Query query, Class type) { - public QueryCursorPreparer(Query query) { this.query = query; + this.type = type; } /* @@ -2164,7 +2179,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { cursorToUse = cursorToUse.limit(query.getLimit()); } if (query.getSortObject() != null) { - cursorToUse = cursorToUse.sort(query.getSortObject()); + cursorToUse = cursorToUse.sort(getMappedSortObject(query, type)); } if (StringUtils.hasText(query.getHint())) { cursorToUse = cursorToUse.hint(query.getHint()); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java index a1f73e443..12c65b337 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java @@ -2593,6 +2593,95 @@ public class MongoTemplateTests { assertThat(template.findOne(query, DocumentWithCollectionOfSimpleType.class).values, hasSize(3)); } + /** + * @see DATAMONGO-888 + */ + @Test + public void sortOnIdFieldPropertyShouldBeMappedCorrectly() { + + DoucmentWithNamedIdField one = new DoucmentWithNamedIdField(); + one.someIdKey = "1"; + one.value = "a"; + + DoucmentWithNamedIdField two = new DoucmentWithNamedIdField(); + two.someIdKey = "2"; + two.value = "b"; + + template.save(one); + template.save(two); + + Query query = query(where("_id").in("1", "2")).with(new Sort(Direction.DESC, "someIdKey")); + assertThat(template.find(query, DoucmentWithNamedIdField.class), contains(two, one)); + } + + /** + * @see DATAMONGO-888 + */ + @Test + public void sortOnAnnotatedFieldPropertyShouldBeMappedCorrectly() { + + DoucmentWithNamedIdField one = new DoucmentWithNamedIdField(); + one.someIdKey = "1"; + one.value = "a"; + + DoucmentWithNamedIdField two = new DoucmentWithNamedIdField(); + two.someIdKey = "2"; + two.value = "b"; + + template.save(one); + template.save(two); + + Query query = query(where("_id").in("1", "2")).with(new Sort(Direction.DESC, "value")); + assertThat(template.find(query, DoucmentWithNamedIdField.class), contains(two, one)); + } + + static class DoucmentWithNamedIdField { + + @Id String someIdKey; + + @Field(value = "val")// + String value; + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + (someIdKey == null ? 0 : someIdKey.hashCode()); + result = prime * result + (value == null ? 0 : value.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof DoucmentWithNamedIdField)) { + return false; + } + DoucmentWithNamedIdField other = (DoucmentWithNamedIdField) obj; + if (someIdKey == null) { + if (other.someIdKey != null) { + return false; + } + } else if (!someIdKey.equals(other.someIdKey)) { + return false; + } + if (value == null) { + if (other.value != null) { + return false; + } + } else if (!value.equals(other.value)) { + return false; + } + return true; + } + + } + static class DocumentWithDBRefCollection { @Id public String id; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/QueryCursorPreparerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/QueryCursorPreparerUnitTests.java index 05f4363c8..e7dff1527 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/QueryCursorPreparerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/QueryCursorPreparerUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011 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. @@ -15,9 +15,9 @@ */ package org.springframework.data.mongodb.core; -import static org.springframework.data.mongodb.core.query.Query.*; -import static org.springframework.data.mongodb.core.query.Criteria.*; import static org.mockito.Mockito.*; +import static org.springframework.data.mongodb.core.query.Criteria.*; +import static org.springframework.data.mongodb.core.query.Query.*; import org.junit.Test; import org.junit.runner.RunWith; @@ -33,14 +33,13 @@ import com.mongodb.DBCursor; * Unit tests for {@link QueryCursorPreparer}. * * @author Oliver Gierke + * @author Christoph Strobl */ @RunWith(MockitoJUnitRunner.class) public class QueryCursorPreparerUnitTests { - @Mock - MongoDbFactory factory; - @Mock - DBCursor cursor; + @Mock MongoDbFactory factory; + @Mock DBCursor cursor; /** * @see DATAMONGO-185 @@ -50,7 +49,7 @@ public class QueryCursorPreparerUnitTests { Query query = query(where("foo").is("bar")).withHint("hint"); - CursorPreparer preparer = new MongoTemplate(factory).new QueryCursorPreparer(query); + CursorPreparer preparer = new MongoTemplate(factory).new QueryCursorPreparer(query, null); preparer.prepare(cursor); verify(cursor).hint("hint");