Compare commits
16 Commits
2.0.1.RELE
...
2.0.2.RELE
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2a81dc75a8 | ||
|
|
58cd4c08ca | ||
|
|
344e019143 | ||
|
|
918b7e96bb | ||
|
|
fce7a5c1cb | ||
|
|
dbd2de8e0f | ||
|
|
0dbe331ab0 | ||
|
|
846ebcd91d | ||
|
|
9e0b5caeac | ||
|
|
cf70f5e5eb | ||
|
|
331dc6df6f | ||
|
|
a51dce2c90 | ||
|
|
c0cf1aa95b | ||
|
|
7104ffa543 | ||
|
|
28d2fb6680 | ||
|
|
140e26946f |
@@ -31,6 +31,8 @@ cache:
|
||||
directories:
|
||||
- $HOME/.m2
|
||||
|
||||
install: true
|
||||
install:
|
||||
- |-
|
||||
mongo admin --eval "db.adminCommand({setFeatureCompatibilityVersion: '3.4'});"
|
||||
|
||||
script: "mvn clean dependency:list test -P${PROFILE} -Dsort"
|
||||
|
||||
6
pom.xml
6
pom.xml
@@ -5,7 +5,7 @@
|
||||
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>2.0.1.RELEASE</version>
|
||||
<version>2.0.2.RELEASE</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>Spring Data MongoDB</name>
|
||||
@@ -15,7 +15,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data.build</groupId>
|
||||
<artifactId>spring-data-parent</artifactId>
|
||||
<version>2.0.1.RELEASE</version>
|
||||
<version>2.0.2.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
@@ -27,7 +27,7 @@
|
||||
<properties>
|
||||
<project.type>multi</project.type>
|
||||
<dist.id>spring-data-mongodb</dist.id>
|
||||
<springdata.commons>2.0.1.RELEASE</springdata.commons>
|
||||
<springdata.commons>2.0.2.RELEASE</springdata.commons>
|
||||
<mongo>3.5.0</mongo>
|
||||
<mongo.reactivestreams>1.6.0</mongo.reactivestreams>
|
||||
<jmh.version>1.19</jmh.version>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>2.0.1.RELEASE</version>
|
||||
<version>2.0.2.RELEASE</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>2.0.1.RELEASE</version>
|
||||
<version>2.0.2.RELEASE</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb</artifactId>
|
||||
<version>2.0.1.RELEASE</version>
|
||||
<version>2.0.2.RELEASE</version>
|
||||
</dependency>
|
||||
|
||||
<!-- reactive -->
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>2.0.1.RELEASE</version>
|
||||
<version>2.0.2.RELEASE</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>2.0.1.RELEASE</version>
|
||||
<version>2.0.2.RELEASE</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -43,9 +43,10 @@ import com.mongodb.client.MongoDatabase;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link ScriptOperations} capable of saving and executing {@link ServerSideJavaScript}.
|
||||
*
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Oliver Gierke
|
||||
* @author Mark Paluch
|
||||
* @since 1.7
|
||||
*/
|
||||
class DefaultScriptOperations implements ScriptOperations {
|
||||
@@ -141,7 +142,7 @@ class DefaultScriptOperations implements ScriptOperations {
|
||||
|
||||
Assert.hasText(scriptName, "ScriptName must not be null or empty!");
|
||||
|
||||
return mongoOperations.exists(query(where("name").is(scriptName)), NamedMongoScript.class, SCRIPT_COLLECTION_NAME);
|
||||
return mongoOperations.exists(query(where("_id").is(scriptName)), NamedMongoScript.class, SCRIPT_COLLECTION_NAME);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -190,7 +191,7 @@ class DefaultScriptOperations implements ScriptOperations {
|
||||
* Generate a valid name for the {@literal JavaScript}. MongoDB requires an id of type String for scripts. Calling
|
||||
* scripts having {@link ObjectId} as id fails. Therefore we create a random UUID without {@code -} (as this won't
|
||||
* work) an prefix the result with {@link #SCRIPT_NAME_PREFIX}.
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private static String generateScriptName() {
|
||||
|
||||
@@ -2771,31 +2771,26 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
private class ReadDocumentCallback<T> implements DocumentCallback<T> {
|
||||
|
||||
private final EntityReader<? super T, Bson> reader;
|
||||
private final Class<T> type;
|
||||
private final @NonNull EntityReader<? super T, Bson> reader;
|
||||
private final @NonNull Class<T> type;
|
||||
private final String collectionName;
|
||||
|
||||
public ReadDocumentCallback(EntityReader<? super T, Bson> reader, Class<T> type, String collectionName) {
|
||||
|
||||
Assert.notNull(reader, "EntityReader must not be null!");
|
||||
Assert.notNull(type, "Entity type must not be null!");
|
||||
|
||||
this.reader = reader;
|
||||
this.type = type;
|
||||
this.collectionName = collectionName;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public T doWith(Document object) {
|
||||
public T doWith(@Nullable Document object) {
|
||||
|
||||
if (null != object) {
|
||||
maybeEmitEvent(new AfterLoadEvent<T>(object, type, collectionName));
|
||||
}
|
||||
|
||||
T source = reader.read(type, object);
|
||||
|
||||
if (null != source) {
|
||||
maybeEmitEvent(new AfterConvertEvent<T>(object, source, collectionName));
|
||||
}
|
||||
|
||||
return source;
|
||||
}
|
||||
}
|
||||
@@ -2830,10 +2825,15 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
|
||||
Class<?> typeToRead = targetType.isInterface() || targetType.isAssignableFrom(entityType) ? entityType
|
||||
: targetType;
|
||||
|
||||
if (null != object) {
|
||||
maybeEmitEvent(new AfterLoadEvent<T>(object, targetType, collectionName));
|
||||
}
|
||||
|
||||
Object source = reader.read(typeToRead, object);
|
||||
Object result = targetType.isInterface() ? projectionFactory.createProjection(targetType, source) : source;
|
||||
|
||||
if (result == null) {
|
||||
if (null != result) {
|
||||
maybeEmitEvent(new AfterConvertEvent<>(object, result, collectionName));
|
||||
}
|
||||
|
||||
@@ -2986,7 +2986,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
|
||||
|
||||
T doWith = delegate.doWith(content);
|
||||
|
||||
return new GeoResult<T>(doWith, new Distance(distance, metric));
|
||||
return new GeoResult<>(doWith, new Distance(distance, metric));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -149,6 +149,8 @@ public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T, Mong
|
||||
@Override
|
||||
public void verify() {
|
||||
|
||||
super.verify();
|
||||
|
||||
verifyFieldUniqueness();
|
||||
verifyFieldTypes();
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ inline fun <reified T : Any> MongoOperations.getCollectionName(): String =
|
||||
* @author Sebastien Deleuze
|
||||
* @since 2.0
|
||||
*/
|
||||
inline fun <reified T : Any> MongoOperations.execute(action: CollectionCallback<T>): T =
|
||||
inline fun <reified T : Any> MongoOperations.execute(action: CollectionCallback<T>): T? =
|
||||
execute(T::class.java, action)
|
||||
|
||||
/**
|
||||
@@ -278,7 +278,7 @@ inline fun <reified T : Any> MongoOperations.geoNear(near: NearQuery, collection
|
||||
* @author Sebastien Deleuze
|
||||
* @since 2.0
|
||||
*/
|
||||
inline fun <reified T : Any> MongoOperations.findOne(query: Query, collectionName: String? = null): T =
|
||||
inline fun <reified T : Any> MongoOperations.findOne(query: Query, collectionName: String? = null): T? =
|
||||
if (collectionName != null) findOne(query, T::class.java, collectionName) else findOne(query, T::class.java)
|
||||
|
||||
/**
|
||||
@@ -318,7 +318,7 @@ inline fun <reified T : Any> MongoOperations.find(query: Query, collectionName:
|
||||
* @author Sebastien Deleuze
|
||||
* @since 2.0
|
||||
*/
|
||||
inline fun <reified T : Any> MongoOperations.findById(id: Any, collectionName: String? = null): T =
|
||||
inline fun <reified T : Any> MongoOperations.findById(id: Any, collectionName: String? = null): T? =
|
||||
if (collectionName != null) findById(id, T::class.java, collectionName)
|
||||
else findById(id, T::class.java)
|
||||
|
||||
@@ -328,7 +328,7 @@ inline fun <reified T : Any> MongoOperations.findById(id: Any, collectionName: S
|
||||
* @author Sebastien Deleuze
|
||||
* @since 2.0
|
||||
*/
|
||||
inline fun <reified T : Any> MongoOperations.findAndModify(query: Query, update: Update, options: FindAndModifyOptions, collectionName: String? = null): T =
|
||||
inline fun <reified T : Any> MongoOperations.findAndModify(query: Query, update: Update, options: FindAndModifyOptions, collectionName: String? = null): T? =
|
||||
if (collectionName != null) findAndModify(query, update, options, T::class.java, collectionName)
|
||||
else findAndModify(query, update, options, T::class.java)
|
||||
|
||||
@@ -338,7 +338,7 @@ inline fun <reified T : Any> MongoOperations.findAndModify(query: Query, update:
|
||||
* @author Sebastien Deleuze
|
||||
* @since 2.0
|
||||
*/
|
||||
inline fun <reified T : Any> MongoOperations.findAndRemove(query: Query, collectionName: String? = null): T =
|
||||
inline fun <reified T : Any> MongoOperations.findAndRemove(query: Query, collectionName: String? = null): T? =
|
||||
if (collectionName != null) findAndRemove(query, T::class.java, collectionName)
|
||||
else findAndRemove(query, T::class.java)
|
||||
|
||||
@@ -414,7 +414,6 @@ inline fun <reified T : Any> MongoOperations.updateFirst(query: Query, update: U
|
||||
if (collectionName != null) updateFirst(query, update, T::class.java, collectionName)
|
||||
else updateFirst(query, update, T::class.java)
|
||||
|
||||
|
||||
/**
|
||||
* Extension for [MongoOperations.updateMulti] providing a [KClass] based variant.
|
||||
*
|
||||
|
||||
@@ -129,7 +129,7 @@ public class MongoTemplateUnitTests extends MongoOperationsUnitTests {
|
||||
when(db.runCommand(Mockito.any(), Mockito.any(Class.class))).thenReturn(commandResultDocument);
|
||||
when(collection.find(Mockito.any(org.bson.Document.class))).thenReturn(findIterable);
|
||||
when(collection.mapReduce(Mockito.any(), Mockito.any())).thenReturn(mapReduceIterable);
|
||||
when(collection.count(any(), any())).thenReturn(1L);
|
||||
when(collection.count(any(Bson.class), any(CountOptions.class))).thenReturn(1L);
|
||||
when(findIterable.projection(Mockito.any())).thenReturn(findIterable);
|
||||
when(findIterable.sort(Mockito.any(org.bson.Document.class))).thenReturn(findIterable);
|
||||
when(findIterable.modifiers(Mockito.any(org.bson.Document.class))).thenReturn(findIterable);
|
||||
|
||||
@@ -15,14 +15,17 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.mapping;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.junit.Before;
|
||||
@@ -186,6 +189,19 @@ public class BasicMongoPersistentPropertyUnitTests {
|
||||
assertThat(property.getFieldName(), is("myField"));
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1737
|
||||
public void honorsFieldOrderWhenIteratingOverProperties() {
|
||||
|
||||
MongoMappingContext context = new MongoMappingContext();
|
||||
BasicMongoPersistentEntity<?> entity = context.getPersistentEntity(Sample.class);
|
||||
|
||||
List<String> properties = new ArrayList<>();
|
||||
|
||||
entity.doWithProperties((MongoPersistentProperty property) -> properties.add(property.getName()));
|
||||
|
||||
assertThat(properties).containsExactly("first", "second", "third");
|
||||
}
|
||||
|
||||
private MongoPersistentProperty getPropertyFor(Field field) {
|
||||
return getPropertyFor(entity, field);
|
||||
}
|
||||
@@ -213,6 +229,13 @@ public class BasicMongoPersistentPropertyUnitTests {
|
||||
@org.springframework.data.mongodb.core.mapping.Field(order = -20) String ssn;
|
||||
}
|
||||
|
||||
class Sample {
|
||||
|
||||
@org.springframework.data.mongodb.core.mapping.Field(order = 2) String second;
|
||||
@org.springframework.data.mongodb.core.mapping.Field(order = 3) String third;
|
||||
@org.springframework.data.mongodb.core.mapping.Field(order = 1) String first;
|
||||
}
|
||||
|
||||
enum UppercaseFieldNamingStrategy implements FieldNamingStrategy {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) 2011-2017 by the original author(s).
|
||||
* Copyright 2011-2017 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -15,23 +15,23 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.mapping.event;
|
||||
|
||||
import static org.hamcrest.collection.IsCollectionWithSize.*;
|
||||
import static org.hamcrest.core.Is.*;
|
||||
import static org.hamcrest.core.IsEqual.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.data.mongodb.core.DocumentTestUtils.assertTypeHint;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.springframework.data.mongodb.core.DocumentTestUtils.*;
|
||||
import static org.springframework.data.mongodb.core.query.Criteria.*;
|
||||
import static org.springframework.data.mongodb.core.query.Query.*;
|
||||
|
||||
import java.net.UnknownHostException;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
@@ -41,19 +41,17 @@ import org.springframework.data.mongodb.core.aggregation.Aggregation;
|
||||
import org.springframework.data.mongodb.core.mapping.DBRef;
|
||||
import org.springframework.data.mongodb.core.mapping.PersonPojoStringId;
|
||||
|
||||
import com.mongodb.DB;
|
||||
import com.mongodb.Mongo;
|
||||
import com.mongodb.MongoClient;
|
||||
import com.mongodb.WriteConcern;
|
||||
|
||||
import lombok.Data;
|
||||
import com.mongodb.client.MongoDatabase;
|
||||
|
||||
/**
|
||||
* Integration test for Mapping Events.
|
||||
*
|
||||
*
|
||||
* @author Mark Pollack
|
||||
* @author Christoph Strobl
|
||||
* @author Jordi Llach
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class ApplicationContextEventTests {
|
||||
|
||||
@@ -64,28 +62,40 @@ public class ApplicationContextEventTests {
|
||||
private final String[] collectionsToDrop = new String[] { COLLECTION_NAME, ROOT_COLLECTION_NAME,
|
||||
RELATED_COLLECTION_NAME };
|
||||
|
||||
private static MongoClient mongo;
|
||||
private ApplicationContext applicationContext;
|
||||
private MongoTemplate template;
|
||||
private SimpleMappingEventListener simpleMappingEventListener;
|
||||
private SimpleMappingEventListener listener;
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() {
|
||||
mongo = new MongoClient();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() {
|
||||
mongo.close();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
public void setUp() {
|
||||
|
||||
cleanDb();
|
||||
|
||||
applicationContext = new AnnotationConfigApplicationContext(ApplicationContextEventTestsAppConfig.class);
|
||||
template = applicationContext.getBean(MongoTemplate.class);
|
||||
template.setWriteConcern(WriteConcern.FSYNC_SAFE);
|
||||
simpleMappingEventListener = applicationContext.getBean(SimpleMappingEventListener.class);
|
||||
listener = applicationContext.getBean(SimpleMappingEventListener.class);
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanUp() throws Exception {
|
||||
public void cleanUp() {
|
||||
cleanDb();
|
||||
}
|
||||
|
||||
private void cleanDb() throws UnknownHostException {
|
||||
private void cleanDb() {
|
||||
|
||||
Mongo mongo = new MongoClient();
|
||||
DB db = mongo.getDB("database");
|
||||
MongoDatabase db = mongo.getDatabase("database");
|
||||
for (String coll : collectionsToDrop) {
|
||||
db.getCollection(coll).drop();
|
||||
}
|
||||
@@ -98,23 +108,23 @@ public class ApplicationContextEventTests {
|
||||
PersonBeforeSaveListener personBeforeSaveListener = applicationContext.getBean(PersonBeforeSaveListener.class);
|
||||
AfterSaveListener afterSaveListener = applicationContext.getBean(AfterSaveListener.class);
|
||||
|
||||
assertEquals(0, personBeforeSaveListener.seenEvents.size());
|
||||
assertEquals(0, afterSaveListener.seenEvents.size());
|
||||
assertThat(personBeforeSaveListener.seenEvents).isEmpty();
|
||||
assertThat(afterSaveListener.seenEvents).isEmpty();
|
||||
|
||||
assertEquals(0, simpleMappingEventListener.onBeforeSaveEvents.size());
|
||||
assertEquals(0, simpleMappingEventListener.onAfterSaveEvents.size());
|
||||
assertThat(listener.onBeforeSaveEvents).isEmpty();
|
||||
assertThat(listener.onAfterSaveEvents).isEmpty();
|
||||
|
||||
PersonPojoStringId p = new PersonPojoStringId("1", "Text");
|
||||
template.insert(p);
|
||||
|
||||
assertEquals(1, personBeforeSaveListener.seenEvents.size());
|
||||
assertEquals(1, afterSaveListener.seenEvents.size());
|
||||
assertThat(personBeforeSaveListener.seenEvents).hasSize(1);
|
||||
assertThat(afterSaveListener.seenEvents).hasSize(1);
|
||||
|
||||
assertEquals(1, simpleMappingEventListener.onBeforeSaveEvents.size());
|
||||
assertEquals(1, simpleMappingEventListener.onAfterSaveEvents.size());
|
||||
assertThat(listener.onBeforeSaveEvents).hasSize(1);
|
||||
assertThat(listener.onAfterSaveEvents).hasSize(1);
|
||||
|
||||
assertEquals(COLLECTION_NAME, simpleMappingEventListener.onBeforeSaveEvents.get(0).getCollectionName());
|
||||
assertEquals(COLLECTION_NAME, simpleMappingEventListener.onAfterSaveEvents.get(0).getCollectionName());
|
||||
assertThat(listener.onBeforeSaveEvents.get(0).getCollectionName()).isEqualTo(COLLECTION_NAME);
|
||||
assertThat(listener.onAfterSaveEvents.get(0).getCollectionName()).isEqualTo(COLLECTION_NAME);
|
||||
|
||||
Assert.assertTrue(personBeforeSaveListener.seenEvents.get(0) instanceof BeforeSaveEvent<?>);
|
||||
Assert.assertTrue(afterSaveListener.seenEvents.get(0) instanceof AfterSaveEvent<?>);
|
||||
@@ -142,14 +152,14 @@ public class ApplicationContextEventTests {
|
||||
|
||||
template.findOne(query(where("id").is(entity.getId())), PersonPojoStringId.class);
|
||||
|
||||
assertThat(simpleMappingEventListener.onAfterLoadEvents.size(), is(1));
|
||||
assertThat(simpleMappingEventListener.onAfterLoadEvents.get(0).getCollectionName(), is(COLLECTION_NAME));
|
||||
assertThat(listener.onAfterLoadEvents).hasSize(1);
|
||||
assertThat(listener.onAfterLoadEvents.get(0).getCollectionName()).isEqualTo(COLLECTION_NAME);
|
||||
|
||||
assertThat(simpleMappingEventListener.onBeforeConvertEvents.size(), is(1));
|
||||
assertThat(simpleMappingEventListener.onBeforeConvertEvents.get(0).getCollectionName(), is(COLLECTION_NAME));
|
||||
assertThat(listener.onBeforeConvertEvents).hasSize(1);
|
||||
assertThat(listener.onBeforeConvertEvents.get(0).getCollectionName()).isEqualTo(COLLECTION_NAME);
|
||||
|
||||
assertThat(simpleMappingEventListener.onAfterConvertEvents.size(), is(1));
|
||||
assertThat(simpleMappingEventListener.onAfterConvertEvents.get(0).getCollectionName(), is(COLLECTION_NAME));
|
||||
assertThat(listener.onAfterConvertEvents).hasSize(1);
|
||||
assertThat(listener.onAfterConvertEvents.get(0).getCollectionName()).isEqualTo(COLLECTION_NAME);
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1256
|
||||
@@ -160,14 +170,14 @@ public class ApplicationContextEventTests {
|
||||
template.aggregate(Aggregation.newAggregation(Aggregation.project("text")), PersonPojoStringId.class,
|
||||
PersonPojoStringId.class);
|
||||
|
||||
assertThat(simpleMappingEventListener.onAfterLoadEvents.size(), is(1));
|
||||
assertThat(simpleMappingEventListener.onAfterLoadEvents.get(0).getCollectionName(), is(COLLECTION_NAME));
|
||||
assertThat(listener.onAfterLoadEvents).hasSize(1);
|
||||
assertThat(listener.onAfterLoadEvents.get(0).getCollectionName()).isEqualTo(COLLECTION_NAME);
|
||||
|
||||
assertThat(simpleMappingEventListener.onBeforeConvertEvents.size(), is(1));
|
||||
assertThat(simpleMappingEventListener.onBeforeConvertEvents.get(0).getCollectionName(), is(COLLECTION_NAME));
|
||||
assertThat(listener.onBeforeConvertEvents).hasSize(1);
|
||||
assertThat(listener.onBeforeConvertEvents.get(0).getCollectionName()).isEqualTo(COLLECTION_NAME);
|
||||
|
||||
assertThat(simpleMappingEventListener.onAfterConvertEvents.size(), is(1));
|
||||
assertThat(simpleMappingEventListener.onAfterConvertEvents.get(0).getCollectionName(), is(COLLECTION_NAME));
|
||||
assertThat(listener.onAfterConvertEvents).hasSize(1);
|
||||
assertThat(listener.onAfterConvertEvents.get(0).getCollectionName()).isEqualTo(COLLECTION_NAME);
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1256
|
||||
@@ -178,15 +188,15 @@ public class ApplicationContextEventTests {
|
||||
|
||||
template.remove(entity);
|
||||
|
||||
assertThat(simpleMappingEventListener.onBeforeDeleteEvents.size(), is(1));
|
||||
assertThat(simpleMappingEventListener.onBeforeDeleteEvents.get(0).getCollectionName(), is(COLLECTION_NAME));
|
||||
assertThat(listener.onBeforeDeleteEvents).hasSize(1);
|
||||
assertThat(listener.onBeforeDeleteEvents.get(0).getCollectionName()).isEqualTo(COLLECTION_NAME);
|
||||
|
||||
assertThat(simpleMappingEventListener.onAfterDeleteEvents.size(), is(1));
|
||||
assertThat(simpleMappingEventListener.onAfterDeleteEvents.get(0).getCollectionName(), is(COLLECTION_NAME));
|
||||
assertThat(listener.onAfterDeleteEvents).hasSize(1);
|
||||
assertThat(listener.onAfterDeleteEvents.get(0).getCollectionName()).isEqualTo(COLLECTION_NAME);
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1271
|
||||
public void publishesAfterLoadAndAfterConvertEventsForDBRef() throws Exception {
|
||||
public void publishesAfterLoadAndAfterConvertEventsForDBRef() {
|
||||
|
||||
Related ref1 = new Related(2L, "related desc1");
|
||||
|
||||
@@ -200,21 +210,17 @@ public class ApplicationContextEventTests {
|
||||
|
||||
template.findOne(query(where("id").is(source.getId())), Root.class);
|
||||
|
||||
assertThat(simpleMappingEventListener.onAfterLoadEvents, hasSize(2));
|
||||
assertThat(simpleMappingEventListener.onAfterLoadEvents.get(0).getCollectionName(),
|
||||
is(equalTo(ROOT_COLLECTION_NAME)));
|
||||
assertThat(simpleMappingEventListener.onAfterLoadEvents.get(1).getCollectionName(),
|
||||
is(equalTo(RELATED_COLLECTION_NAME)));
|
||||
assertThat(listener.onAfterLoadEvents).hasSize(2);
|
||||
assertThat(listener.onAfterLoadEvents.get(0).getCollectionName()).isEqualTo(ROOT_COLLECTION_NAME);
|
||||
assertThat(listener.onAfterLoadEvents.get(1).getCollectionName()).isEqualTo(RELATED_COLLECTION_NAME);
|
||||
|
||||
assertThat(simpleMappingEventListener.onAfterConvertEvents, hasSize(2));
|
||||
assertThat(simpleMappingEventListener.onAfterConvertEvents.get(0).getCollectionName(),
|
||||
is(equalTo(RELATED_COLLECTION_NAME)));
|
||||
assertThat(simpleMappingEventListener.onAfterConvertEvents.get(1).getCollectionName(),
|
||||
is(equalTo(ROOT_COLLECTION_NAME)));
|
||||
assertThat(listener.onAfterConvertEvents).hasSize(2);
|
||||
assertThat(listener.onAfterConvertEvents.get(0).getCollectionName()).isEqualTo(RELATED_COLLECTION_NAME);
|
||||
assertThat(listener.onAfterConvertEvents.get(1).getCollectionName()).isEqualTo(ROOT_COLLECTION_NAME);
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1271
|
||||
public void publishesAfterLoadAndAfterConvertEventsForLazyLoadingDBRef() throws Exception {
|
||||
public void publishesAfterLoadAndAfterConvertEventsForLazyLoadingDBRef() {
|
||||
|
||||
Related ref1 = new Related(2L, "related desc1");
|
||||
|
||||
@@ -228,27 +234,23 @@ public class ApplicationContextEventTests {
|
||||
|
||||
Root target = template.findOne(query(where("id").is(source.getId())), Root.class);
|
||||
|
||||
assertThat(simpleMappingEventListener.onAfterLoadEvents, hasSize(1));
|
||||
assertThat(simpleMappingEventListener.onAfterLoadEvents.get(0).getCollectionName(),
|
||||
is(equalTo(ROOT_COLLECTION_NAME)));
|
||||
assertThat(listener.onAfterLoadEvents).hasSize(1);
|
||||
assertThat(listener.onAfterLoadEvents.get(0).getCollectionName()).isEqualTo(ROOT_COLLECTION_NAME);
|
||||
|
||||
assertThat(simpleMappingEventListener.onAfterConvertEvents, hasSize(1));
|
||||
assertThat(simpleMappingEventListener.onAfterConvertEvents.get(0).getCollectionName(),
|
||||
is(equalTo(ROOT_COLLECTION_NAME)));
|
||||
assertThat(listener.onAfterConvertEvents).hasSize(1);
|
||||
assertThat(listener.onAfterConvertEvents.get(0).getCollectionName()).isEqualTo(ROOT_COLLECTION_NAME);
|
||||
|
||||
target.getLazyReference().getDescription();
|
||||
|
||||
assertThat(simpleMappingEventListener.onAfterLoadEvents, hasSize(2));
|
||||
assertThat(simpleMappingEventListener.onAfterLoadEvents.get(1).getCollectionName(),
|
||||
is(equalTo(RELATED_COLLECTION_NAME)));
|
||||
assertThat(listener.onAfterLoadEvents).hasSize(2);
|
||||
assertThat(listener.onAfterLoadEvents.get(1).getCollectionName()).isEqualTo(RELATED_COLLECTION_NAME);
|
||||
|
||||
assertThat(simpleMappingEventListener.onAfterConvertEvents, hasSize(2));
|
||||
assertThat(simpleMappingEventListener.onAfterConvertEvents.get(1).getCollectionName(),
|
||||
is(equalTo(RELATED_COLLECTION_NAME)));
|
||||
assertThat(listener.onAfterConvertEvents).hasSize(2);
|
||||
assertThat(listener.onAfterConvertEvents.get(1).getCollectionName()).isEqualTo(RELATED_COLLECTION_NAME);
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1271
|
||||
public void publishesAfterLoadAndAfterConvertEventsForListOfDBRef() throws Exception {
|
||||
public void publishesAfterLoadAndAfterConvertEventsForListOfDBRef() {
|
||||
|
||||
List<Related> references = Arrays.asList(new Related(20L, "ref 1"), new Related(30L, "ref 2"));
|
||||
|
||||
@@ -262,25 +264,19 @@ public class ApplicationContextEventTests {
|
||||
|
||||
template.findOne(query(where("id").is(source.getId())), Root.class);
|
||||
|
||||
assertThat(simpleMappingEventListener.onAfterLoadEvents, hasSize(3));
|
||||
assertThat(simpleMappingEventListener.onAfterLoadEvents.get(0).getCollectionName(),
|
||||
is(equalTo(ROOT_COLLECTION_NAME)));
|
||||
assertThat(simpleMappingEventListener.onAfterLoadEvents.get(1).getCollectionName(),
|
||||
is(equalTo(RELATED_COLLECTION_NAME)));
|
||||
assertThat(simpleMappingEventListener.onAfterLoadEvents.get(2).getCollectionName(),
|
||||
is(equalTo(RELATED_COLLECTION_NAME)));
|
||||
assertThat(listener.onAfterLoadEvents).hasSize(3);
|
||||
assertThat(listener.onAfterLoadEvents.get(0).getCollectionName()).isEqualTo(ROOT_COLLECTION_NAME);
|
||||
assertThat(listener.onAfterLoadEvents.get(1).getCollectionName()).isEqualTo(RELATED_COLLECTION_NAME);
|
||||
assertThat(listener.onAfterLoadEvents.get(2).getCollectionName()).isEqualTo(RELATED_COLLECTION_NAME);
|
||||
|
||||
assertThat(simpleMappingEventListener.onAfterConvertEvents, hasSize(3));
|
||||
assertThat(simpleMappingEventListener.onAfterConvertEvents.get(0).getCollectionName(),
|
||||
is(equalTo(RELATED_COLLECTION_NAME)));
|
||||
assertThat(simpleMappingEventListener.onAfterConvertEvents.get(1).getCollectionName(),
|
||||
is(equalTo(RELATED_COLLECTION_NAME)));
|
||||
assertThat(simpleMappingEventListener.onAfterConvertEvents.get(2).getCollectionName(),
|
||||
is(equalTo(ROOT_COLLECTION_NAME)));
|
||||
assertThat(listener.onAfterConvertEvents).hasSize(3);
|
||||
assertThat(listener.onAfterConvertEvents.get(0).getCollectionName()).isEqualTo(RELATED_COLLECTION_NAME);
|
||||
assertThat(listener.onAfterConvertEvents.get(1).getCollectionName()).isEqualTo(RELATED_COLLECTION_NAME);
|
||||
assertThat(listener.onAfterConvertEvents.get(2).getCollectionName()).isEqualTo(ROOT_COLLECTION_NAME);
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1271
|
||||
public void publishesAfterLoadAndAfterConvertEventsForLazyLoadingListOfDBRef() throws Exception {
|
||||
public void publishesAfterLoadAndAfterConvertEventsForLazyLoadingListOfDBRef() {
|
||||
|
||||
List<Related> references = Arrays.asList(new Related(20L, "ref 1"), new Related(30L, "ref 2"));
|
||||
|
||||
@@ -294,30 +290,24 @@ public class ApplicationContextEventTests {
|
||||
|
||||
Root target = template.findOne(query(where("id").is(source.getId())), Root.class);
|
||||
|
||||
assertThat(simpleMappingEventListener.onAfterLoadEvents, hasSize(1));
|
||||
assertThat(simpleMappingEventListener.onAfterLoadEvents.get(0).getCollectionName(),
|
||||
is(equalTo(ROOT_COLLECTION_NAME)));
|
||||
assertThat(simpleMappingEventListener.onAfterConvertEvents, hasSize(1));
|
||||
assertThat(simpleMappingEventListener.onAfterConvertEvents.get(0).getCollectionName(),
|
||||
is(equalTo(ROOT_COLLECTION_NAME)));
|
||||
assertThat(listener.onAfterLoadEvents).hasSize(1);
|
||||
assertThat(listener.onAfterLoadEvents.get(0).getCollectionName()).isEqualTo(ROOT_COLLECTION_NAME);
|
||||
assertThat(listener.onAfterConvertEvents).hasSize(1);
|
||||
assertThat(listener.onAfterConvertEvents.get(0).getCollectionName()).isEqualTo(ROOT_COLLECTION_NAME);
|
||||
|
||||
target.getLazyListOfReferences().size();
|
||||
|
||||
assertThat(simpleMappingEventListener.onAfterLoadEvents, hasSize(3));
|
||||
assertThat(simpleMappingEventListener.onAfterConvertEvents, hasSize(3));
|
||||
assertThat(listener.onAfterLoadEvents).hasSize(3);
|
||||
assertThat(listener.onAfterConvertEvents).hasSize(3);
|
||||
|
||||
assertThat(simpleMappingEventListener.onAfterLoadEvents.get(1).getCollectionName(),
|
||||
is(equalTo(RELATED_COLLECTION_NAME)));
|
||||
assertThat(simpleMappingEventListener.onAfterLoadEvents.get(2).getCollectionName(),
|
||||
is(equalTo(RELATED_COLLECTION_NAME)));
|
||||
assertThat(simpleMappingEventListener.onAfterConvertEvents.get(1).getCollectionName(),
|
||||
is(equalTo(RELATED_COLLECTION_NAME)));
|
||||
assertThat(simpleMappingEventListener.onAfterConvertEvents.get(2).getCollectionName(),
|
||||
is(equalTo(RELATED_COLLECTION_NAME)));
|
||||
assertThat(listener.onAfterLoadEvents.get(1).getCollectionName()).isEqualTo(RELATED_COLLECTION_NAME);
|
||||
assertThat(listener.onAfterLoadEvents.get(2).getCollectionName()).isEqualTo(RELATED_COLLECTION_NAME);
|
||||
assertThat(listener.onAfterConvertEvents.get(1).getCollectionName()).isEqualTo(RELATED_COLLECTION_NAME);
|
||||
assertThat(listener.onAfterConvertEvents.get(2).getCollectionName()).isEqualTo(RELATED_COLLECTION_NAME);
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1271
|
||||
public void publishesAfterLoadAndAfterConvertEventsForMapOfDBRef() throws Exception {
|
||||
public void publishesAfterLoadAndAfterConvertEventsForMapOfDBRef() {
|
||||
|
||||
Map<String, Related> references = new LinkedHashMap<String, Related>();
|
||||
references.put("ref-1", new Related(20L, "ref 1"));
|
||||
@@ -333,25 +323,19 @@ public class ApplicationContextEventTests {
|
||||
|
||||
template.findOne(query(where("id").is(source.getId())), Root.class);
|
||||
|
||||
assertThat(simpleMappingEventListener.onAfterLoadEvents, hasSize(3));
|
||||
assertThat(simpleMappingEventListener.onAfterLoadEvents.get(0).getCollectionName(),
|
||||
is(equalTo(ROOT_COLLECTION_NAME)));
|
||||
assertThat(simpleMappingEventListener.onAfterLoadEvents.get(1).getCollectionName(),
|
||||
is(equalTo(RELATED_COLLECTION_NAME)));
|
||||
assertThat(simpleMappingEventListener.onAfterLoadEvents.get(2).getCollectionName(),
|
||||
is(equalTo(RELATED_COLLECTION_NAME)));
|
||||
assertThat(listener.onAfterLoadEvents).hasSize(3);
|
||||
assertThat(listener.onAfterLoadEvents.get(0).getCollectionName()).isEqualTo(ROOT_COLLECTION_NAME);
|
||||
assertThat(listener.onAfterLoadEvents.get(1).getCollectionName()).isEqualTo(RELATED_COLLECTION_NAME);
|
||||
assertThat(listener.onAfterLoadEvents.get(2).getCollectionName()).isEqualTo(RELATED_COLLECTION_NAME);
|
||||
|
||||
assertThat(simpleMappingEventListener.onAfterConvertEvents, hasSize(3));
|
||||
assertThat(simpleMappingEventListener.onAfterConvertEvents.get(0).getCollectionName(),
|
||||
is(equalTo(RELATED_COLLECTION_NAME)));
|
||||
assertThat(simpleMappingEventListener.onAfterConvertEvents.get(1).getCollectionName(),
|
||||
is(equalTo(RELATED_COLLECTION_NAME)));
|
||||
assertThat(simpleMappingEventListener.onAfterConvertEvents.get(2).getCollectionName(),
|
||||
is(equalTo(ROOT_COLLECTION_NAME)));
|
||||
assertThat(listener.onAfterConvertEvents).hasSize(3);
|
||||
assertThat(listener.onAfterConvertEvents.get(0).getCollectionName()).isEqualTo(RELATED_COLLECTION_NAME);
|
||||
assertThat(listener.onAfterConvertEvents.get(1).getCollectionName()).isEqualTo(RELATED_COLLECTION_NAME);
|
||||
assertThat(listener.onAfterConvertEvents.get(2).getCollectionName()).isEqualTo(ROOT_COLLECTION_NAME);
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1271
|
||||
public void publishesAfterLoadAndAfterConvertEventsForLazyLoadingMapOfDBRef() throws Exception {
|
||||
public void publishesAfterLoadAndAfterConvertEventsForLazyLoadingMapOfDBRef() {
|
||||
|
||||
Map<String, Related> references = new LinkedHashMap<String, Related>();
|
||||
references.put("ref-1", new Related(20L, "ref 1"));
|
||||
@@ -367,36 +351,48 @@ public class ApplicationContextEventTests {
|
||||
|
||||
Root target = template.findOne(query(where("id").is(source.getId())), Root.class);
|
||||
|
||||
assertThat(simpleMappingEventListener.onAfterLoadEvents, hasSize(1));
|
||||
assertThat(simpleMappingEventListener.onAfterLoadEvents.get(0).getCollectionName(),
|
||||
is(equalTo(ROOT_COLLECTION_NAME)));
|
||||
assertThat(listener.onAfterLoadEvents).hasSize(1);
|
||||
assertThat(listener.onAfterLoadEvents.get(0).getCollectionName()).isEqualTo(ROOT_COLLECTION_NAME);
|
||||
|
||||
assertThat(simpleMappingEventListener.onAfterConvertEvents, hasSize(1));
|
||||
assertThat(simpleMappingEventListener.onAfterConvertEvents.get(0).getCollectionName(),
|
||||
is(equalTo(ROOT_COLLECTION_NAME)));
|
||||
assertThat(listener.onAfterConvertEvents).hasSize(1);
|
||||
assertThat(listener.onAfterConvertEvents.get(0).getCollectionName()).isEqualTo(ROOT_COLLECTION_NAME);
|
||||
|
||||
target.getLazyMapOfReferences().size();
|
||||
|
||||
assertThat(simpleMappingEventListener.onAfterLoadEvents, hasSize(3));
|
||||
assertThat(simpleMappingEventListener.onAfterLoadEvents.get(1).getCollectionName(),
|
||||
is(equalTo(RELATED_COLLECTION_NAME)));
|
||||
assertThat(simpleMappingEventListener.onAfterLoadEvents.get(2).getCollectionName(),
|
||||
is(equalTo(RELATED_COLLECTION_NAME)));
|
||||
assertThat(listener.onAfterLoadEvents).hasSize(3);
|
||||
assertThat(listener.onAfterLoadEvents.get(1).getCollectionName()).isEqualTo(RELATED_COLLECTION_NAME);
|
||||
assertThat(listener.onAfterLoadEvents.get(2).getCollectionName()).isEqualTo(RELATED_COLLECTION_NAME);
|
||||
|
||||
assertThat(simpleMappingEventListener.onAfterConvertEvents, hasSize(3));
|
||||
assertThat(simpleMappingEventListener.onAfterConvertEvents.get(1).getCollectionName(),
|
||||
is(equalTo(RELATED_COLLECTION_NAME)));
|
||||
assertThat(simpleMappingEventListener.onAfterConvertEvents.get(2).getCollectionName(),
|
||||
is(equalTo(RELATED_COLLECTION_NAME)));
|
||||
assertThat(listener.onAfterConvertEvents).hasSize(3);
|
||||
assertThat(listener.onAfterConvertEvents.get(1).getCollectionName()).isEqualTo(RELATED_COLLECTION_NAME);
|
||||
assertThat(listener.onAfterConvertEvents.get(2).getCollectionName()).isEqualTo(RELATED_COLLECTION_NAME);
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1823
|
||||
public void publishesAfterConvertEventForFindQueriesUsingProjections() {
|
||||
|
||||
PersonPojoStringId entity = new PersonPojoStringId("1", "Text");
|
||||
template.insert(entity);
|
||||
|
||||
template.query(PersonPojoStringId.class).matching(query(where("id").is(entity.getId()))).all();
|
||||
|
||||
assertThat(listener.onAfterLoadEvents).hasSize(1);
|
||||
assertThat(listener.onAfterLoadEvents.get(0).getCollectionName()).isEqualTo(COLLECTION_NAME);
|
||||
|
||||
assertThat(listener.onBeforeConvertEvents).hasSize(1);
|
||||
assertThat(listener.onBeforeConvertEvents.get(0).getCollectionName()).isEqualTo(COLLECTION_NAME);
|
||||
|
||||
assertThat(listener.onAfterConvertEvents).hasSize(1);
|
||||
assertThat(listener.onAfterConvertEvents.get(0).getCollectionName()).isEqualTo(COLLECTION_NAME);
|
||||
}
|
||||
|
||||
private void comparePersonAndDocument(PersonPojoStringId p, PersonPojoStringId p2, org.bson.Document document) {
|
||||
|
||||
assertEquals(p.getId(), p2.getId());
|
||||
assertEquals(p.getText(), p2.getText());
|
||||
assertThat(p2.getId()).isEqualTo(p.getId());
|
||||
assertThat(p2.getText()).isEqualTo(p.getText());
|
||||
|
||||
assertEquals("1", document.get("_id"));
|
||||
assertEquals("Text", document.get("text"));
|
||||
assertThat(document.get("_id")).isEqualTo("1");
|
||||
assertThat(document.get("text")).isEqualTo("Text");
|
||||
assertTypeHint(document, PersonPojoStringId.class);
|
||||
}
|
||||
|
||||
|
||||
@@ -190,10 +190,30 @@ public interface PersonRepository extends ReactiveMongoRepository<Person, String
|
||||
[[mongo.reactive.repositories.infinite-streams]]
|
||||
== Infinite Streams with Tailable Cursors
|
||||
|
||||
By default, MongoDB will automatically close a cursor when the client has exhausted all results in the cursor. Closing a cursors turns a Stream into a finite stream. However, for capped collections you may use a https://docs.mongodb.com/manual/core/tailable-cursors/[Tailable Cursor] that remains open after the client exhausts the results in the initial cursor. Using tailable Cursors with a reactive approach allows construction of infinite streams. A tailable Cursor remains open until it's closed. It emits data as data arrives in a capped collection. Using Tailable Cursors with Collections is not possible as its result would never complete.
|
||||
By default, MongoDB will automatically close a cursor when the client exhausts all results supplied by the cursor. Closing a cursor on exhaustion turns a stream into a finite stream. For https://docs.mongodb.com/manual/core/capped-collections/[capped collections] you may use a https://docs.mongodb.com/manual/core/tailable-cursors/[Tailable Cursor] that remains open after the client consumes all initially returned data. Using tailable cursors with a reactive data types allows construction of infinite streams. A tailable cursor remains open until it is closed externally. It emits data as new documents arrive in a capped collection.
|
||||
|
||||
Spring Data MongoDB Reactive Repository support supports infinite streams by annotating a query method with `@TailableCursor`. This works for methods returning `Flux` or `Observable` wrapper types.
|
||||
Tailable cursors may become dead, or invalid, if either the query returns no match or the cursor returns the document at the "end" of the collection and then the application deletes that document.
|
||||
|
||||
|
||||
.Infinite Stream queries with ReactiveMongoOperations
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
Flux<Person> stream = template.tail(query(where("name").is("Joe")), Person.class);
|
||||
|
||||
Disposable subscription = stream.doOnNext(person -> System.out.println(person)).subscribe();
|
||||
|
||||
// …
|
||||
|
||||
// Later: Dispose the subscription to close the stream
|
||||
subscription.dispose();
|
||||
----
|
||||
====
|
||||
|
||||
Spring Data MongoDB Reactive repositories support infinite streams by annotating a query method with `@Tailable`. This works for methods returning `Flux` and other reactive types capable of emitting multiple elements.
|
||||
|
||||
.Infinite Stream queries with ReactiveMongoRepository
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
|
||||
@@ -210,6 +230,9 @@ Disposable subscription = stream.doOnNext(System.out::println).subscribe();
|
||||
|
||||
// …
|
||||
|
||||
// Later: Dispose the stream
|
||||
// Later: Dispose the subscription to close the stream
|
||||
subscription.dispose();
|
||||
----
|
||||
====
|
||||
|
||||
TIP: Capped collections can be created via `MongoOperations.createCollection`. Just provide the required `CollectionOptions.empty().capped()...`
|
||||
|
||||
@@ -457,24 +457,6 @@ NOTE: This example is meant to show the use of save, update and remove operation
|
||||
|
||||
The query syntax used in the example is explained in more detail in the section <<mongo.query,Querying Documents>>. Additional documentation can be found in <<mongo-template, the blocking MongoTemplate>> section.
|
||||
|
||||
[[mongo.reactive.tailcursors]]
|
||||
== Infinite Streams
|
||||
|
||||
By default, MongoDB will automatically close a cursor when the client has exhausted all results in the cursor. Closing a cursors turns a Stream into a finite stream. However, for capped collections you may use a https://docs.mongodb.com/manual/core/tailable-cursors/[Tailable Cursor] that remains open after the client exhausts the results in the initial cursor. Using Tailable Cursors with a reactive approach allows construction of infinite streams. A Tailable Cursor remains open until it's closed. It emits data as data arrives in a capped collection. Using Tailable Cursors with Collections is not possible as its result would never complete.
|
||||
|
||||
[source,java]
|
||||
----
|
||||
Flux<Person> stream = template.tail(query(where("name").is("Joe")), Person.class);
|
||||
|
||||
Disposable subscription = stream.doOnNext(person -> System.out.println(person)).subscribe();
|
||||
|
||||
// …
|
||||
|
||||
// Later: Dispose the stream
|
||||
subscription.dispose();
|
||||
----
|
||||
|
||||
|
||||
[[mongo.reactive.executioncallback]]
|
||||
== Execution callbacks
|
||||
|
||||
|
||||
@@ -1,6 +1,23 @@
|
||||
Spring Data MongoDB Changelog
|
||||
=============================
|
||||
|
||||
Changes in version 2.0.2.RELEASE (2017-11-27)
|
||||
---------------------------------------------
|
||||
* DATAMONGO-1823 - AfterConvertEvent is not published when using custom methods in repository interface.
|
||||
* DATAMONGO-1821 - Fix method ambiguity in tests when compiling against MongoDB 3.6.
|
||||
* DATAMONGO-1820 - Investigate failing TravisCI build.
|
||||
* DATAMONGO-1818 - Reference documentation mentions @TailableCursor instead of @Tailable.
|
||||
* DATAMONGO-1817 - Kotlin extensions should return nullable types.
|
||||
* DATAMONGO-1816 - Release 2.0.2 (Kay SR2).
|
||||
|
||||
|
||||
Changes in version 1.10.9.RELEASE (2017-11-27)
|
||||
----------------------------------------------
|
||||
* DATAMONGO-1809 - Type hint usage broken when using positional parameters with more than one digit.
|
||||
* DATAMONGO-1799 - Release 1.10.9 (Ingalls SR9).
|
||||
* DATAMONGO-1696 - Reference documentation uses JPA Annotations.
|
||||
|
||||
|
||||
Changes in version 2.0.1.RELEASE (2017-10-27)
|
||||
---------------------------------------------
|
||||
* DATAMONGO-1815 - Adapt API changes in Property in test cases.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Spring Data MongoDB 2.0.1
|
||||
Spring Data MongoDB 2.0.2
|
||||
Copyright (c) [2010-2015] Pivotal Software, Inc.
|
||||
|
||||
This product is licensed to you under the Apache License, Version 2.0 (the "License").
|
||||
|
||||
Reference in New Issue
Block a user