Browse Source

DATAMONGO-2323 - Fix query(…) and stream(…) to be used with BSON Document.

MongoTemplate.stream(…), MongoTemplate.query(…) and ReactiveMongoTemplate.query(…) now no longer fail when used with BSON Document.class.

Previously, field mapping failed because it required an entity type. Now we gracefully back off when find methods are used with a simple Document entity type.
pull/773/head
Mark Paluch 7 years ago
parent
commit
1f146c3b5c
  1. 18
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java
  2. 19
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java
  3. 7
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupportTests.java
  4. 12
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java
  5. 6
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveFindOperationSupportTests.java

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

@ -418,8 +418,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
* @see org.springframework.data.mongodb.core.MongoOperations#executeAsStream(org.springframework.data.mongodb.core.query.Query, java.lang.Class) * @see org.springframework.data.mongodb.core.MongoOperations#executeAsStream(org.springframework.data.mongodb.core.query.Query, java.lang.Class)
*/ */
@Override @Override
public <T> CloseableIterator<T> stream(final Query query, final Class<T> entityType) { public <T> CloseableIterator<T> stream(Query query, Class<T> entityType) {
return stream(query, entityType, getCollectionName(entityType)); return stream(query, entityType, getCollectionName(entityType));
} }
@ -428,12 +427,12 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
* @see org.springframework.data.mongodb.core.MongoOperations#stream(org.springframework.data.mongodb.core.query.Query, java.lang.Class, java.lang.String) * @see org.springframework.data.mongodb.core.MongoOperations#stream(org.springframework.data.mongodb.core.query.Query, java.lang.Class, java.lang.String)
*/ */
@Override @Override
public <T> CloseableIterator<T> stream(final Query query, final Class<T> entityType, final String collectionName) { public <T> CloseableIterator<T> stream(Query query, Class<T> entityType, String collectionName) {
return doStream(query, entityType, collectionName, entityType); return doStream(query, entityType, collectionName, entityType);
} }
@SuppressWarnings("ConstantConditions") @SuppressWarnings("ConstantConditions")
protected <T> CloseableIterator<T> doStream(final Query query, final Class<?> entityType, final String collectionName, protected <T> CloseableIterator<T> doStream(Query query, final Class<?> entityType, String collectionName,
Class<T> returnType) { Class<T> returnType) {
Assert.notNull(query, "Query must not be null!"); Assert.notNull(query, "Query must not be null!");
@ -443,7 +442,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
return execute(collectionName, (CollectionCallback<CloseableIterator<T>>) collection -> { return execute(collectionName, (CollectionCallback<CloseableIterator<T>>) collection -> {
MongoPersistentEntity<?> persistentEntity = mappingContext.getRequiredPersistentEntity(entityType); MongoPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(entityType);
Document mappedFields = getMappedFieldsObject(query.getFieldsObject(), persistentEntity, returnType); Document mappedFields = getMappedFieldsObject(query.getFieldsObject(), persistentEntity, returnType);
Document mappedQuery = queryMapper.getMappedObject(query.getQueryObject(), persistentEntity); Document mappedQuery = queryMapper.getMappedObject(query.getQueryObject(), persistentEntity);
@ -2523,7 +2522,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
<S, T> List<T> doFind(String collectionName, Document query, Document fields, Class<S> sourceClass, <S, T> List<T> doFind(String collectionName, Document query, Document fields, Class<S> sourceClass,
Class<T> targetClass, CursorPreparer preparer) { Class<T> targetClass, CursorPreparer preparer) {
MongoPersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(sourceClass); MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(sourceClass);
Document mappedFields = getMappedFieldsObject(fields, entity, targetClass); Document mappedFields = getMappedFieldsObject(fields, entity, targetClass);
Document mappedQuery = queryMapper.getMappedObject(query, entity); Document mappedQuery = queryMapper.getMappedObject(query, entity);
@ -2860,7 +2859,12 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
return queryMapper.getMappedSort(query.getSortObject(), mappingContext.getPersistentEntity(type)); return queryMapper.getMappedSort(query.getSortObject(), mappingContext.getPersistentEntity(type));
} }
private Document getMappedFieldsObject(Document fields, MongoPersistentEntity<?> entity, Class<?> targetType) { private Document getMappedFieldsObject(Document fields, @Nullable MongoPersistentEntity<?> entity,
Class<?> targetType) {
if (entity == null) {
return fields;
}
Document projectedFields = propertyOperations.computeFieldsForProjection(projectionFactory, fields, Document projectedFields = propertyOperations.computeFieldsForProjection(projectionFactory, fields,
entity.getType(), targetType); entity.getType(), targetType);

19
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java

@ -436,8 +436,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
* @see org.springframework.data.mongodb.core.ReactiveMongoOperations#reactiveIndexOps(java.lang.Class) * @see org.springframework.data.mongodb.core.ReactiveMongoOperations#reactiveIndexOps(java.lang.Class)
*/ */
public ReactiveIndexOperations indexOps(Class<?> entityClass) { public ReactiveIndexOperations indexOps(Class<?> entityClass) {
return new DefaultReactiveIndexOperations(this, getCollectionName(entityClass), this.queryMapper, return new DefaultReactiveIndexOperations(this, getCollectionName(entityClass), this.queryMapper, entityClass);
entityClass);
} }
public String getCollectionName(Class<?> entityClass) { public String getCollectionName(Class<?> entityClass) {
@ -697,8 +696,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
() -> operations.forType(entityClass).getCollation()) // () -> operations.forType(entityClass).getCollation()) //
.map(options::collation).orElse(options); .map(options::collation).orElse(options);
return doCreateCollection(getCollectionName(entityClass), return doCreateCollection(getCollectionName(entityClass), convertToCreateCollectionOptions(options, entityClass));
convertToCreateCollectionOptions(options, entityClass));
} }
/* /*
@ -2103,8 +2101,8 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
public <T> Flux<T> mapReduce(Query filterQuery, Class<?> domainType, Class<T> resultType, String mapFunction, public <T> Flux<T> mapReduce(Query filterQuery, Class<?> domainType, Class<T> resultType, String mapFunction,
String reduceFunction, MapReduceOptions options) { String reduceFunction, MapReduceOptions options) {
return mapReduce(filterQuery, domainType, getCollectionName(domainType), resultType, mapFunction, return mapReduce(filterQuery, domainType, getCollectionName(domainType), resultType, mapFunction, reduceFunction,
reduceFunction, options); options);
} }
/* /*
@ -2402,7 +2400,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
<S, T> Flux<T> doFind(String collectionName, Document query, Document fields, Class<S> sourceClass, <S, T> Flux<T> doFind(String collectionName, Document query, Document fields, Class<S> sourceClass,
Class<T> targetClass, FindPublisherPreparer preparer) { Class<T> targetClass, FindPublisherPreparer preparer) {
MongoPersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(sourceClass); MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(sourceClass);
Document mappedFields = getMappedFieldsObject(fields, entity, targetClass); Document mappedFields = getMappedFieldsObject(fields, entity, targetClass);
Document mappedQuery = queryMapper.getMappedObject(query, entity); Document mappedQuery = queryMapper.getMappedObject(query, entity);
@ -2416,7 +2414,12 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
new ProjectingReadCallback<>(mongoConverter, sourceClass, targetClass, collectionName), collectionName); new ProjectingReadCallback<>(mongoConverter, sourceClass, targetClass, collectionName), collectionName);
} }
private Document getMappedFieldsObject(Document fields, MongoPersistentEntity<?> entity, Class<?> targetType) { private Document getMappedFieldsObject(Document fields, @Nullable MongoPersistentEntity<?> entity,
Class<?> targetType) {
if (entity == null) {
return fields;
}
Document projectedFields = propertyOperations.computeFieldsForProjection(projectionFactory, fields, Document projectedFields = propertyOperations.computeFieldsForProjection(projectionFactory, fields,
entity.getType(), targetType); entity.getType(), targetType);

7
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupportTests.java

@ -147,6 +147,13 @@ public class ExecutableFindOperationSupportTests {
.hasSize(1); .hasSize(1);
} }
@Test // DATAMONGO-2323
public void findAllAsDocument() {
assertThat(
template.query(Document.class).inCollection(STAR_WARS).matching(query(where("firstname").is("luke"))).all())
.hasSize(1);
}
@Test // DATAMONGO-1563 @Test // DATAMONGO-1563
public void findAllByWithProjection() { public void findAllByWithProjection() {

12
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java

@ -3355,7 +3355,7 @@ public class MongoTemplateTests {
assertThat(loaded.bigDeciamVal).isEqualTo(new BigDecimal("800")); assertThat(loaded.bigDeciamVal).isEqualTo(new BigDecimal("800"));
} }
@Test // DATAMONGO-1431 @Test // DATAMONGO-1431, DATAMONGO-2323
public void streamExecutionUsesExplicitCollectionName() { public void streamExecutionUsesExplicitCollectionName() {
template.remove(new Query(), "some_special_collection"); template.remove(new Query(), "some_special_collection");
@ -3366,14 +3366,14 @@ public class MongoTemplateTests {
template.insert(document, "some_special_collection"); template.insert(document, "some_special_collection");
CloseableIterator<Document> stream = template.stream(new Query(), Document.class); CloseableIterator<Document> stream = template.stream(new Query(), Document.class);
assertThat(stream.hasNext()).isFalse(); assertThat(stream.hasNext()).isFalse();
stream = template.stream(new Query(), Document.class, "some_special_collection"); CloseableIterator<org.bson.Document> stream2 = template.stream(new Query(where("_id").is(document.id)),
org.bson.Document.class, "some_special_collection");
assertThat(stream.hasNext()).isTrue(); assertThat(stream2.hasNext()).isTrue();
assertThat(stream.next().id).isEqualTo(document.id); assertThat(stream2.next().get("_id")).isEqualTo(new ObjectId(document.id));
assertThat(stream.hasNext()).isFalse(); assertThat(stream2.hasNext()).isFalse();
} }
@Test // DATAMONGO-1194 @Test // DATAMONGO-1194

6
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveFindOperationSupportTests.java

@ -134,6 +134,12 @@ public class ReactiveFindOperationSupportTests {
StepVerifier.create(template.query(Human.class).inCollection(STAR_WARS).all()).expectNextCount(2).verifyComplete(); StepVerifier.create(template.query(Human.class).inCollection(STAR_WARS).all()).expectNextCount(2).verifyComplete();
} }
@Test // DATAMONGO-2323
public void findAllAsDocumentDocument() {
StepVerifier.create(template.query(Document.class).inCollection(STAR_WARS).all()).expectNextCount(2)
.verifyComplete();
}
@Test // DATAMONGO-1719 @Test // DATAMONGO-1719
public void findAllWithProjection() { public void findAllWithProjection() {

Loading…
Cancel
Save