Compare commits

...

14 Commits

Author SHA1 Message Date
Mark Paluch
3ee696dab2 Release version 3.0.9 (Neumann SR9).
See #3597
2021-04-14 11:04:45 +02:00
Mark Paluch
7ee12e9637 Prepare 3.0.9 (Neumann SR9).
See #3597
2021-04-14 11:04:07 +02:00
Mark Paluch
414d716c07 Updated changelog.
See #3597
2021-04-14 11:03:59 +02:00
Mark Paluch
5f9e25cd8a Polishing.
Fix nullability annotations for isEqual(…) parameters. Fix generics. Reformat code.

Add tests.

See #3414
Original pull request: #3615.
2021-04-13 09:44:41 +02:00
Clement Petit
caa2dd4e85 Handle nested Pattern and Document in Criteria.equals(…).
Closes #3414
Original pull request: #3615.
2021-04-13 09:44:41 +02:00
Mark Paluch
28fc1e4823 Polishing.
Use ObjectUtils for empty check.

See #3623
Original pull request: #3625.
2021-04-13 09:09:49 +02:00
Christoph Strobl
d62639d11c Fix NPE in declarative aggregation execution.
This commit fixes an issue where using a simple return type leads to NPE when the actual aggregation result does not contain any values.

Closes: #3623
Original pull request: #3625.
2021-04-13 09:09:49 +02:00
Mark Paluch
b13e47d8ac Updated changelog.
See #3598
2021-03-31 18:30:47 +02:00
Mark Paluch
3743ca56df Updated changelog.
See #3595
2021-03-31 17:26:07 +02:00
Clément Petit
0f974130d1 Return saved entity reference instead of original reference.
Make SimpleReactiveMongoRepository#saveAll(Publisher<S>) return the saved entity references instead of the original references.

Closes #3609
Original pull request: #3611.
2021-03-29 11:03:44 +02:00
Mark Paluch
020da42800 Updated changelog.
See #3558
2021-03-17 11:31:31 +01:00
Mark Paluch
4307b4cd91 Updated changelog.
See #3561
2021-03-17 11:03:42 +01:00
Mark Paluch
af874b635c After release cleanups.
See #3556
2021-03-17 10:33:57 +01:00
Mark Paluch
017e01810d Prepare next development iteration.
See #3556
2021-03-17 10:33:55 +01:00
12 changed files with 251 additions and 18 deletions

View File

@@ -5,7 +5,7 @@
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>3.0.8.RELEASE</version>
<version>3.0.9.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.3.8.RELEASE</version>
<version>2.3.9.RELEASE</version>
</parent>
<modules>
@@ -26,7 +26,7 @@
<properties>
<project.type>multi</project.type>
<dist.id>spring-data-mongodb</dist.id>
<springdata.commons>2.3.8.RELEASE</springdata.commons>
<springdata.commons>2.3.9.RELEASE</springdata.commons>
<mongo>4.0.6</mongo>
<mongo.reactivestreams>${mongo}</mongo.reactivestreams>
<jmh.version>1.19</jmh.version>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>3.0.8.RELEASE</version>
<version>3.0.9.RELEASE</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@@ -14,7 +14,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>3.0.8.RELEASE</version>
<version>3.0.9.RELEASE</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@@ -11,7 +11,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>3.0.8.RELEASE</version>
<version>3.0.9.RELEASE</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@@ -20,8 +20,10 @@ import static org.springframework.util.ObjectUtils.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@@ -58,6 +60,7 @@ import com.mongodb.BasicDBList;
* @author Christoph Strobl
* @author Mark Paluch
* @author Andreas Zink
* @author Clément Petit
*/
public class Criteria implements CriteriaDefinition {
@@ -895,15 +898,15 @@ public class Criteria implements CriteriaDefinition {
* @param right
* @return
*/
private boolean isEqual(Object left, Object right) {
private boolean isEqual(@Nullable Object left, @Nullable Object right) {
if (left == null) {
return right == null;
}
if (Pattern.class.isInstance(left)) {
if (left instanceof Pattern) {
if (!Pattern.class.isInstance(right)) {
if (!(right instanceof Pattern)) {
return false;
}
@@ -914,6 +917,52 @@ public class Criteria implements CriteriaDefinition {
&& leftPattern.flags() == rightPattern.flags();
}
if (left instanceof Document) {
if (!(right instanceof Document)) {
return false;
}
Document leftDocument = (Document) left;
Document rightDocument = (Document) right;
Iterator<Entry<String, Object>> leftIterator = leftDocument.entrySet().iterator();
Iterator<Entry<String, Object>> rightIterator = rightDocument.entrySet().iterator();
while (leftIterator.hasNext() && rightIterator.hasNext()) {
Map.Entry<String, Object> leftEntry = leftIterator.next();
Map.Entry<String, Object> rightEntry = rightIterator.next();
if (!isEqual(leftEntry.getKey(), rightEntry.getKey())
|| !isEqual(leftEntry.getValue(), rightEntry.getValue())) {
return false;
}
}
return !leftIterator.hasNext() && !rightIterator.hasNext();
}
if (Collection.class.isAssignableFrom(left.getClass())) {
if (!Collection.class.isAssignableFrom(right.getClass())) {
return false;
}
Collection<?> leftCollection = (Collection<?>) left;
Collection<?> rightCollection = (Collection<?>) right;
Iterator<?> leftIterator = leftCollection.iterator();
Iterator<?> rightIterator = rightCollection.iterator();
while (leftIterator.hasNext() && rightIterator.hasNext()) {
if (!isEqual(leftIterator.next(), rightIterator.next())) {
return false;
}
}
return !leftIterator.hasNext() && !rightIterator.hasNext();
}
return ObjectUtils.nullSafeEquals(left, right);
}

View File

@@ -39,6 +39,7 @@ import org.springframework.data.repository.query.QueryMethodEvaluationContextPro
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
/**
@@ -196,9 +197,9 @@ class AggregationUtils {
* @throws IllegalArgumentException when none of the above rules is met.
*/
@Nullable
static <T> T extractSimpleTypeResult(Document source, Class<T> targetType, MongoConverter converter) {
static <T> T extractSimpleTypeResult(@Nullable Document source, Class<T> targetType, MongoConverter converter) {
if (source.isEmpty()) {
if (ObjectUtils.isEmpty(source)) {
return null;
}

View File

@@ -49,6 +49,7 @@ import com.mongodb.client.result.DeleteResult;
* @author Oliver Gierke
* @author Christoph Strobl
* @author Ruben J Garcia
* @author Clément Petit
* @since 2.0
*/
@RequiredArgsConstructor
@@ -326,8 +327,8 @@ public class SimpleReactiveMongoRepository<T, ID extends Serializable> implement
Assert.notNull(entityStream, "The given Publisher of entities must not be null!");
return Flux.from(entityStream).flatMap(entity -> entityInformation.isNew(entity) ? //
mongoOperations.insert(entity, entityInformation.getCollectionName()).then(Mono.just(entity)) : //
mongoOperations.save(entity, entityInformation.getCollectionName()).then(Mono.just(entity)));
mongoOperations.insert(entity, entityInformation.getCollectionName()) : //
mongoOperations.save(entity, entityInformation.getCollectionName()));
}
/*

View File

@@ -34,6 +34,8 @@ import org.springframework.data.mongodb.core.schema.MongoJsonSchema;
* @author Thomas Darimont
* @author Christoph Strobl
* @author Andreas Zink
* @author Clément Petit
* @author Mark Paluch
*/
public class CriteriaUnitTests {
@@ -310,9 +312,72 @@ public class CriteriaUnitTests {
@Test // DATAMONGO-2002
public void shouldEqualForSamePattern() {
Criteria left = new Criteria("field").regex("foo");
Criteria right = new Criteria("field").regex("foo");
assertThat(left).isEqualTo(right);
}
@Test // DATAMONGO-2002
public void shouldEqualForDocument() {
assertThat(new Criteria("field").is(new Document("one", 1).append("two", "two").append("null", null)))
.isEqualTo(new Criteria("field").is(new Document("one", 1).append("two", "two").append("null", null)));
assertThat(new Criteria("field").is(new Document("one", 1).append("two", "two").append("null", null)))
.isNotEqualTo(new Criteria("field").is(new Document("one", 1).append("two", "two")));
assertThat(new Criteria("field").is(new Document("one", 1).append("two", "two")))
.isNotEqualTo(new Criteria("field").is(new Document("one", 1).append("two", "two").append("null", null)));
assertThat(new Criteria("field").is(new Document("one", 1).append("null", null).append("two", "two")))
.isNotEqualTo(new Criteria("field").is(new Document("one", 1).append("two", "two").append("null", null)));
assertThat(new Criteria("field").is(new Document())).isNotEqualTo(new Criteria("field").is("foo"));
assertThat(new Criteria("field").is("foo")).isNotEqualTo(new Criteria("field").is(new Document()));
}
@Test // DATAMONGO-2002
public void shouldEqualForCollection() {
assertThat(new Criteria("field").is(Arrays.asList("foo", "bar")))
.isEqualTo(new Criteria("field").is(Arrays.asList("foo", "bar")));
assertThat(new Criteria("field").is(Arrays.asList("foo", 1)))
.isNotEqualTo(new Criteria("field").is(Arrays.asList("foo", "bar")));
assertThat(new Criteria("field").is(Collections.singletonList("foo")))
.isNotEqualTo(new Criteria("field").is(Arrays.asList("foo", "bar")));
assertThat(new Criteria("field").is(Arrays.asList("foo", "bar")))
.isNotEqualTo(new Criteria("field").is(Collections.singletonList("foo")));
assertThat(new Criteria("field").is(Arrays.asList("foo", "bar"))).isNotEqualTo(new Criteria("field").is("foo"));
assertThat(new Criteria("field").is("foo")).isNotEqualTo(new Criteria("field").is(Arrays.asList("foo", "bar")));
}
@Test // GH-3414
public void shouldEqualForSamePatternAndFlags() {
Criteria left = new Criteria("field").regex("foo", "iu");
Criteria right = new Criteria("field").regex("foo");
assertThat(left).isNotEqualTo(right);
}
@Test // GH-3414
public void shouldEqualForNestedPattern() {
Criteria left = new Criteria("a").orOperator(
new Criteria("foo").regex("value", "i"),
new Criteria("bar").regex("value")
);
Criteria right = new Criteria("a").orOperator(
new Criteria("foo").regex("value", "i"),
new Criteria("bar").regex("value")
);
assertThat(left).isEqualTo(right);
}
}

View File

@@ -20,16 +20,19 @@ import static org.springframework.data.domain.ExampleMatcher.*;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.Value;
import lombok.With;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import java.util.Arrays;
import javax.annotation.Nullable;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.BeanFactory;
@@ -55,6 +58,7 @@ import org.springframework.util.ClassUtils;
* @author Mark Paluch
* @author Christoph Strobl
* @author Ruben J Garcia
* @author Clément Petit
*/
@RunWith(SpringRunner.class)
@ContextConfiguration("classpath:reactive-infrastructure.xml")
@@ -65,9 +69,11 @@ public class SimpleReactiveMongoRepositoryTests implements BeanClassLoaderAware,
ReactiveMongoRepositoryFactory factory;
ClassLoader classLoader;
BeanFactory beanFactory;
ReactivePersonRepostitory repository;
ReactivePersonRepository repository;
ReactiveImmutablePersonRepository immutableRepository;
private ReactivePerson dave, oliver, carter, boyd, stefan, leroi, alicia;
private ImmutableReactivePerson keith, james, mariah;
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
@@ -88,9 +94,11 @@ public class SimpleReactiveMongoRepositoryTests implements BeanClassLoaderAware,
factory.setBeanFactory(beanFactory);
factory.setEvaluationContextProvider(QueryMethodEvaluationContextProvider.DEFAULT);
repository = factory.getRepository(ReactivePersonRepostitory.class);
repository = factory.getRepository(ReactivePersonRepository.class);
immutableRepository = factory.getRepository(ReactiveImmutablePersonRepository.class);
repository.deleteAll().as(StepVerifier::create).verifyComplete();
immutableRepository.deleteAll().as(StepVerifier::create).verifyComplete();
dave = new ReactivePerson("Dave", "Matthews", 42);
oliver = new ReactivePerson("Oliver August", "Matthews", 4);
@@ -99,6 +107,9 @@ public class SimpleReactiveMongoRepositoryTests implements BeanClassLoaderAware,
stefan = new ReactivePerson("Stefan", "Lessard", 34);
leroi = new ReactivePerson("Leroi", "Moore", 41);
alicia = new ReactivePerson("Alicia", "Keys", 30);
keith = new ImmutableReactivePerson(null, "Keith", "Urban", 53);
james = new ImmutableReactivePerson(null, "James", "Arthur", 33);
mariah = new ImmutableReactivePerson(null, "Mariah", "Carey", 51);
repository.saveAll(Arrays.asList(oliver, dave, carter, boyd, stefan, leroi, alicia)).as(StepVerifier::create) //
.expectNextCount(7) //
@@ -324,6 +335,20 @@ public class SimpleReactiveMongoRepositoryTests implements BeanClassLoaderAware,
assertThat(boyd.getId()).isNotNull();
}
@Test // GH-3609
public void savePublisherOfImmutableEntitiesShouldInsertEntity() {
immutableRepository.deleteAll().as(StepVerifier::create).verifyComplete();
immutableRepository.saveAll(Flux.just(keith, james, mariah)).as(StepVerifier::create)
.consumeNextWith(e -> keith = e).consumeNextWith(e -> james = e).consumeNextWith(e -> mariah = e)
.verifyComplete();
assertThat(keith.getId()).isNotNull();
assertThat(james.getId()).isNotNull();
assertThat(mariah.getId()).isNotNull();
}
@Test // DATAMONGO-1444
public void deleteAllShouldRemoveEntities() {
@@ -452,12 +477,16 @@ public class SimpleReactiveMongoRepositoryTests implements BeanClassLoaderAware,
repository.findOne(example).as(StepVerifier::create).verifyComplete();
}
interface ReactivePersonRepostitory extends ReactiveMongoRepository<ReactivePerson, String> {
interface ReactivePersonRepository extends ReactiveMongoRepository<ReactivePerson, String> {
Flux<ReactivePerson> findByLastname(String lastname);
}
interface ReactiveImmutablePersonRepository extends ReactiveMongoRepository<ImmutableReactivePerson, String> {
}
@Data
@NoArgsConstructor
static class ReactivePerson {
@@ -475,4 +504,23 @@ public class SimpleReactiveMongoRepositoryTests implements BeanClassLoaderAware,
this.age = age;
}
}
@With
@Value
static class ImmutableReactivePerson {
@Id String id;
String firstname;
String lastname;
int age;
public ImmutableReactivePerson(@Nullable String id, String firstname, String lastname, int age) {
this.id = id;
this.firstname = firstname;
this.lastname = lastname;
this.age = age;
}
}
}

View File

@@ -156,6 +156,14 @@ public class StringBasedAggregationUnitTests {
assertThat(executeAggregation("returnCollection").result).isEqualTo(expected);
}
@Test // GH-3623
public void returnNullWhenSingleResultIsNotPresent() {
when(aggregationResults.getMappedResults()).thenReturn(Collections.emptyList());
assertThat(executeAggregation("simpleReturnType").result).isNull();
}
@Test // DATAMONGO-2153
public void returnRawResultType() {
assertThat(executeAggregation("returnRawResultType").result).isEqualTo(aggregationResults);
@@ -299,6 +307,9 @@ public class StringBasedAggregationUnitTests {
@Aggregation(RAW_GROUP_BY_LASTNAME_STRING)
Page<Person> invalidPageReturnType(Pageable page);
@Aggregation(RAW_GROUP_BY_LASTNAME_STRING)
String simpleReturnType();
}
static class PersonAggregate {

View File

@@ -1,6 +1,58 @@
Spring Data MongoDB Changelog
=============================
Changes in version 3.0.9.RELEASE (2021-04-14)
---------------------------------------------
* #3623 - `@Aggregation` repository query method causes `NullPointerException` when the result is empty.
* #3609 - SimpleReactiveMongoRepository#saveAll does not populate @Id property if it is immutable.
* #3414 - Criteria or toEquals fail if contains regex [DATAMONGO-2559].
Changes in version 3.1.7 (2021-03-31)
-------------------------------------
* #3613 - Use StringUtils.replace(…) instead of String.replaceAll(…) for mapKeyDotReplacement.
* #3609 - SimpleReactiveMongoRepository#saveAll does not populate @Id property if it is immutable.
Changes in version 3.2.0-RC1 (2021-03-31)
-----------------------------------------
* #3613 - Use StringUtils.replace(…) instead of String.replaceAll(…) for mapKeyDotReplacement.
* #3609 - SimpleReactiveMongoRepository#saveAll does not populate @Id property if it is immutable.
* #3600 - Rename Embedded annotation -> Unwrapped.
* #3583 - Support aggregation expression on fields projection.
Changes in version 3.2.0-M5 (2021-03-17)
----------------------------------------
* #3592 - Remove @Persistent from entity-scan include filters.
* #3590 - Embedded sharding keys are not correctly picked up from the shardKeySource Document.
* #3580 - Fix CustomConverter conversion lookup.
* #3579 - Upgrade to MongoDB Java Drivers 4.2.2.
* #3575 - Introduce ConversionContext and clean up MappingMongoConverter.
* #3573 - Json Schema section appears twice in reference documentation.
* #3571 - Introduce ConversionContext and clean up MappingMongoConverter.
* #3570 - Incorrect class casting cause ClassCastException when save java.util.Collection using MongoTemplate.
* #3568 - MongoSocketWriteException may be translated into DataAccessResourceFailureException.
* #3566 - Couldn't find PersistentEntity for type java.lang.Object when updating a field with suffix "class".
* #3552 - UpdateMapper drops numeric keys in Maps.
* #3395 - Derived findBy…IgnoreCaseIn query doesn't return expected results [DATAMONGO-2540].
* #3286 - Add possibility to use Collection<Criteria> as parameter in and/or/nor operators [DATAMONGO-2428].
* #2911 - ensureNotIterable in MongoTemplate only checks for array type [DATAMONGO-2044].
* #590 - DATAMONGO-2044 make ensureNotIterable actually check if object is iterable.
Changes in version 3.1.6 (2021-03-17)
-------------------------------------
* #3592 - Remove @Persistent from entity-scan include filters.
* #3590 - Embedded sharding keys are not correctly picked up from the shardKeySource Document.
* #3589 - Upgrade to MongoDB Driver 4.1.2.
* #3573 - Json Schema section appears twice in reference documentation.
* #3568 - MongoSocketWriteException may be translated into DataAccessResourceFailureException.
* #3566 - Couldn't find PersistentEntity for type java.lang.Object when updating a field with suffix "class".
* #3552 - UpdateMapper drops numeric keys in Maps.
* #3395 - Derived findBy…IgnoreCaseIn query doesn't return expected results [DATAMONGO-2540].
Changes in version 3.0.8.RELEASE (2021-03-17)
---------------------------------------------
* #3590 - Embedded sharding keys are not correctly picked up from the shardKeySource Document.
@@ -3350,6 +3402,11 @@ Repository

View File

@@ -1,4 +1,4 @@
Spring Data MongoDB 3.0.8 (Neumann SR8)
Spring Data MongoDB 3.0.9 (Neumann SR9)
Copyright (c) [2010-2019] Pivotal Software, Inc.
This product is licensed to you under the Apache License, Version 2.0 (the "License").
@@ -23,3 +23,4 @@ conditions of the subcomponent's license, as noted in the LICENSE file.