Compare commits
16 Commits
2.0.11.REL
...
2.0.12.REL
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2b47f44531 | ||
|
|
79534fa426 | ||
|
|
b8e76ecae4 | ||
|
|
3e2b060611 | ||
|
|
4699219728 | ||
|
|
a483d95cde | ||
|
|
84f35f5655 | ||
|
|
2ec0f93325 | ||
|
|
48f9422a66 | ||
|
|
a2349405af | ||
|
|
e12ab354f7 | ||
|
|
04b20fa9c0 | ||
|
|
81c46f04d6 | ||
|
|
ce905c80fe | ||
|
|
831e4f9ef1 | ||
|
|
5ce293a871 |
6
pom.xml
6
pom.xml
@@ -5,7 +5,7 @@
|
||||
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>2.0.11.RELEASE</version>
|
||||
<version>2.0.12.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.11.RELEASE</version>
|
||||
<version>2.0.12.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.11.RELEASE</springdata.commons>
|
||||
<springdata.commons>2.0.12.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.11.RELEASE</version>
|
||||
<version>2.0.12.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.11.RELEASE</version>
|
||||
<version>2.0.12.RELEASE</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb</artifactId>
|
||||
<version>2.0.11.RELEASE</version>
|
||||
<version>2.0.12.RELEASE</version>
|
||||
</dependency>
|
||||
|
||||
<!-- reactive -->
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>2.0.11.RELEASE</version>
|
||||
<version>2.0.12.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.11.RELEASE</version>
|
||||
<version>2.0.12.RELEASE</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -60,6 +60,7 @@ import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexCre
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||
import org.springframework.data.mongodb.core.mapping.event.ValidatingMongoEventListener;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -75,6 +76,7 @@ import org.w3c.dom.Element;
|
||||
* @author Thomas Darimont
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
* @author Zied Yaich
|
||||
*/
|
||||
public class MappingMongoConverterParser implements BeanDefinitionParser {
|
||||
|
||||
@@ -159,6 +161,7 @@ public class MappingMongoConverterParser implements BeanDefinitionParser {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private BeanDefinition potentiallyCreateValidatingMongoEventListener(Element element, ParserContext parserContext) {
|
||||
|
||||
String disableValidation = element.getAttribute("disable-validation");
|
||||
@@ -180,6 +183,7 @@ public class MappingMongoConverterParser implements BeanDefinitionParser {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private RuntimeBeanReference getValidator(Object source, ParserContext parserContext) {
|
||||
|
||||
if (!JSR_303_PRESENT) {
|
||||
@@ -197,7 +201,7 @@ public class MappingMongoConverterParser implements BeanDefinitionParser {
|
||||
}
|
||||
|
||||
public static String potentiallyCreateMappingContext(Element element, ParserContext parserContext,
|
||||
BeanDefinition conversionsDefinition, String converterId) {
|
||||
@Nullable BeanDefinition conversionsDefinition, @Nullable String converterId) {
|
||||
|
||||
String ctxRef = element.getAttribute("mapping-context-ref");
|
||||
|
||||
@@ -211,7 +215,7 @@ public class MappingMongoConverterParser implements BeanDefinitionParser {
|
||||
BeanDefinitionBuilder mappingContextBuilder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(MongoMappingContext.class);
|
||||
|
||||
Set<String> classesToAdd = getInititalEntityClasses(element);
|
||||
Set<String> classesToAdd = getInitialEntityClasses(element);
|
||||
|
||||
if (classesToAdd != null) {
|
||||
mappingContextBuilder.addPropertyValue("initialEntitySet", classesToAdd);
|
||||
@@ -262,6 +266,7 @@ public class MappingMongoConverterParser implements BeanDefinitionParser {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private BeanDefinition getCustomConversions(Element element, ParserContext parserContext) {
|
||||
|
||||
List<Element> customConvertersElements = DomUtils.getChildElementsByTagName(element, "custom-converters");
|
||||
@@ -269,7 +274,7 @@ public class MappingMongoConverterParser implements BeanDefinitionParser {
|
||||
if (customConvertersElements.size() == 1) {
|
||||
|
||||
Element customerConvertersElement = customConvertersElements.get(0);
|
||||
ManagedList<BeanMetadataElement> converterBeans = new ManagedList<BeanMetadataElement>();
|
||||
ManagedList<BeanMetadataElement> converterBeans = new ManagedList<>();
|
||||
List<Element> converterElements = DomUtils.getChildElementsByTagName(customerConvertersElement, "converter");
|
||||
|
||||
if (converterElements != null) {
|
||||
@@ -285,9 +290,7 @@ public class MappingMongoConverterParser implements BeanDefinitionParser {
|
||||
provider.addExcludeFilter(new NegatingFilter(new AssignableTypeFilter(Converter.class),
|
||||
new AssignableTypeFilter(GenericConverter.class)));
|
||||
|
||||
for (BeanDefinition candidate : provider.findCandidateComponents(packageToScan)) {
|
||||
converterBeans.add(candidate);
|
||||
}
|
||||
converterBeans.addAll(provider.findCandidateComponents(packageToScan));
|
||||
}
|
||||
|
||||
BeanDefinitionBuilder conversionsBuilder = BeanDefinitionBuilder.rootBeanDefinition(MongoCustomConversions.class);
|
||||
@@ -304,7 +307,8 @@ public class MappingMongoConverterParser implements BeanDefinitionParser {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Set<String> getInititalEntityClasses(Element element) {
|
||||
@Nullable
|
||||
private static Set<String> getInitialEntityClasses(Element element) {
|
||||
|
||||
String basePackage = element.getAttribute(BASE_PACKAGE);
|
||||
|
||||
@@ -317,7 +321,7 @@ public class MappingMongoConverterParser implements BeanDefinitionParser {
|
||||
componentProvider.addIncludeFilter(new AnnotationTypeFilter(Document.class));
|
||||
componentProvider.addIncludeFilter(new AnnotationTypeFilter(Persistent.class));
|
||||
|
||||
Set<String> classes = new ManagedSet<String>();
|
||||
Set<String> classes = new ManagedSet<>();
|
||||
for (BeanDefinition candidate : componentProvider.findCandidateComponents(basePackage)) {
|
||||
classes.add(candidate.getBeanClassName());
|
||||
}
|
||||
@@ -325,6 +329,7 @@ public class MappingMongoConverterParser implements BeanDefinitionParser {
|
||||
return classes;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public BeanMetadataElement parseConverter(Element element, ParserContext parserContext) {
|
||||
|
||||
String converterRef = element.getAttribute("ref");
|
||||
@@ -375,7 +380,7 @@ public class MappingMongoConverterParser implements BeanDefinitionParser {
|
||||
|
||||
Assert.notNull(filters, "TypeFilters must not be null");
|
||||
|
||||
this.delegates = new HashSet<TypeFilter>(Arrays.asList(filters));
|
||||
this.delegates = new HashSet<>(Arrays.asList(filters));
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -578,7 +578,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
return;
|
||||
}
|
||||
|
||||
MongoPersistentEntity<?> entity = isSubtype(prop.getType(), obj.getClass())
|
||||
MongoPersistentEntity<?> entity = isSubTypeOf(obj.getClass(), prop.getType())
|
||||
? mappingContext.getRequiredPersistentEntity(obj.getClass())
|
||||
: mappingContext.getRequiredPersistentEntity(type);
|
||||
|
||||
@@ -590,10 +590,6 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
accessor.put(prop, document);
|
||||
}
|
||||
|
||||
private boolean isSubtype(Class<?> left, Class<?> right) {
|
||||
return left.isAssignableFrom(right) && !left.equals(right);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns given object as {@link Collection}. Will return the {@link Collection} as is if the source is a
|
||||
* {@link Collection} already, will convert an array into a {@link Collection} or simply create a single element
|
||||
@@ -970,7 +966,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
Assert.notNull(path, "Object path must not be null!");
|
||||
|
||||
Class<?> collectionType = targetType.getType();
|
||||
collectionType = Collection.class.isAssignableFrom(collectionType) //
|
||||
collectionType = isSubTypeOf(collectionType, Collection.class) //
|
||||
? collectionType //
|
||||
: List.class;
|
||||
|
||||
@@ -1544,6 +1540,17 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given type is a sub type of the given reference, i.e. assignable but not the exact same type.
|
||||
*
|
||||
* @param type must not be {@literal null}.
|
||||
* @param reference must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
private static boolean isSubTypeOf(Class<?> type, Class<?> reference) {
|
||||
return !type.equals(reference) && reference.isAssignableFrom(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Marker class used to indicate we have a non root document object here that might be used within an update - so we
|
||||
* need to preserve type hints for potential nested elements but need to remove it on top level.
|
||||
|
||||
@@ -20,7 +20,9 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
|
||||
import org.bson.BSON;
|
||||
import org.bson.Document;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -37,6 +39,7 @@ import org.springframework.util.StringUtils;
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.DBRef;
|
||||
import com.mongodb.util.JSON;
|
||||
import com.mongodb.util.JSONCallback;
|
||||
|
||||
/**
|
||||
* Query to use a plain JSON String to create the {@link Query} to actually execute.
|
||||
@@ -224,7 +227,8 @@ public class StringBasedMongoQuery extends AbstractMongoQuery {
|
||||
String transformedInput = transformQueryAndCollectExpressionParametersIntoBindings(input, bindings);
|
||||
String parseableInput = makeParameterReferencesParseable(transformedInput);
|
||||
|
||||
collectParameterReferencesIntoBindings(bindings, JSON.parse(parseableInput));
|
||||
collectParameterReferencesIntoBindings(bindings,
|
||||
JSON.parse(parseableInput, new LenientPatternDecodingCallback()));
|
||||
|
||||
return transformedInput;
|
||||
}
|
||||
@@ -359,6 +363,43 @@ public class StringBasedMongoQuery extends AbstractMongoQuery {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link JSONCallback} with lenient handling for {@link PatternSyntaxException} falling back to a placeholder
|
||||
* {@link Pattern} for intermediate query document rendering.
|
||||
*/
|
||||
private static class LenientPatternDecodingCallback extends JSONCallback {
|
||||
|
||||
private static final Pattern EMPTY_MARKER = Pattern.compile("__Spring_Data_MongoDB_Bind_Marker__");
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see com.mongodb.util.JSONCallback#objectDone()
|
||||
*/
|
||||
@Override
|
||||
public Object objectDone() {
|
||||
return exceptionSwallowingStackReducingObjectDone();
|
||||
}
|
||||
|
||||
private Object exceptionSwallowingStackReducingObjectDone/*CauseWeJustNeedTheStructureNotTheActualValue*/() {
|
||||
|
||||
Object value;
|
||||
|
||||
try {
|
||||
return super.objectDone();
|
||||
} catch (PatternSyntaxException e) {
|
||||
value = EMPTY_MARKER;
|
||||
}
|
||||
|
||||
if (!isStackEmpty()) {
|
||||
_put(curName(), value);
|
||||
} else {
|
||||
value = !BSON.hasDecodeHooks() ? value : BSON.applyDecodingHooks(value);
|
||||
setRoot(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A generic parameter binding with name or position information.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2017 the original author or authors.
|
||||
* Copyright 2011-2018 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.
|
||||
@@ -26,28 +26,14 @@ import static org.junit.Assert.fail;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.springframework.data.mongodb.core.DocumentTestUtils.*;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.net.URL;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.EnumMap;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
import java.util.*;
|
||||
|
||||
import org.bson.types.ObjectId;
|
||||
import org.hamcrest.Matcher;
|
||||
@@ -1904,6 +1890,18 @@ public class MappingMongoConverterUnitTests {
|
||||
assertThat(target).doesNotContainKeys("_class");
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-2135
|
||||
public void addsEqualObjectsToCollection() {
|
||||
|
||||
org.bson.Document itemDocument = new org.bson.Document("itemKey", "123");
|
||||
org.bson.Document orderDocument = new org.bson.Document("items",
|
||||
Arrays.asList(itemDocument, itemDocument, itemDocument));
|
||||
|
||||
Order order = converter.read(Order.class, orderDocument);
|
||||
|
||||
assertThat(order.items).hasSize(3);
|
||||
}
|
||||
|
||||
static class GenericType<T> {
|
||||
T content;
|
||||
}
|
||||
@@ -2284,4 +2282,15 @@ public class MappingMongoConverterUnitTests {
|
||||
static class WithNestedLists {
|
||||
float[][][] nestedFloats;
|
||||
}
|
||||
|
||||
// DATAMONGO-2135
|
||||
|
||||
@EqualsAndHashCode // equality check by fields
|
||||
static class SomeItem {
|
||||
String itemKey;
|
||||
}
|
||||
|
||||
static class Order {
|
||||
Collection<SomeItem> items = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -590,6 +590,19 @@ public class StringBasedMongoQueryUnitTests {
|
||||
assertThat(query.getQueryObject(), is(new Document("arg0", null)));
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-2119
|
||||
public void spelShouldIgnoreJsonParseErrorsForRegex() {
|
||||
|
||||
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByPersonLastnameRegex", Person.class);
|
||||
ConvertingParameterAccessor accessor = StubParameterAccessor.getAccessor(converter,
|
||||
new Person("Molly", "Chandler"));
|
||||
|
||||
org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accessor);
|
||||
|
||||
assertThat(query.getQueryObject().toJson(),
|
||||
is(new BasicQuery("{lastname: {$regex: 'Chandler'}}").getQueryObject().toJson()));
|
||||
}
|
||||
|
||||
private StringBasedMongoQuery createQueryForMethod(String name, Class<?>... parameters) {
|
||||
|
||||
try {
|
||||
@@ -697,10 +710,14 @@ public class StringBasedMongoQueryUnitTests {
|
||||
@Query("{ 'arg0' : '?0', 'arg1' : '?1s' }")
|
||||
List<Person> findByWhenQuotedAndSomeStuffAppended(String arg0, String arg1);
|
||||
|
||||
@Query("{ 'lastname' : { '$regex' : '^(?0|John ?1|?1)'} }") // use spel or some regex string this is fucking bad
|
||||
@Query("{ 'lastname' : { '$regex' : '^(?0|John ?1|?1)'} }") // use spel or some regex string this is bad
|
||||
Person findByLastnameRegex(String lastname, String alternative);
|
||||
|
||||
@Query("{ arg0 : ?#{[0]} }")
|
||||
List<Person> findByUsingSpel(Object arg0);
|
||||
|
||||
@Query("{ 'lastname' : { '$regex' : ?#{[0].lastname} } }")
|
||||
Person findByPersonLastnameRegex(Person key);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ Note that the domain type shown in the preceding example has a property named `i
|
||||
====
|
||||
[source]
|
||||
----
|
||||
public interface PersonRepository extends PagingAndSortingRepository<Person, Long> {
|
||||
public interface PersonRepository extends PagingAndSortingRepository<Person, String> {
|
||||
|
||||
// additional custom query methods go here
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ Note that the entity defined in the preceding example has a property named `id`
|
||||
====
|
||||
[source]
|
||||
----
|
||||
public interface ReactivePersonRepository extends ReactiveSortingRepository<Person, Long> {
|
||||
public interface ReactivePersonRepository extends ReactiveSortingRepository<Person, String> {
|
||||
|
||||
Flux<Person> findByFirstname(String firstname); <1>
|
||||
|
||||
|
||||
@@ -1,6 +1,36 @@
|
||||
Spring Data MongoDB Changelog
|
||||
=============================
|
||||
|
||||
Changes in version 2.0.12.RELEASE (2018-11-27)
|
||||
----------------------------------------------
|
||||
* DATAMONGO-2135 - Use List instead of Collection when reading data with MappingMongoConverter.
|
||||
* DATAMONGO-2119 - Combining a SpEL expression and a $regex filter triggers a PatternSyntaxException.
|
||||
* DATAMONGO-2118 - Fix typo in repositories reference documentation.
|
||||
* DATAMONGO-2109 - Release 2.0.12 (Kay SR12).
|
||||
* DATAMONGO-2098 - Typo in MappingMongoConverterParser.
|
||||
|
||||
|
||||
Changes in version 1.10.17.RELEASE (2018-11-27)
|
||||
-----------------------------------------------
|
||||
* DATAMONGO-2135 - Use List instead of Collection when reading data with MappingMongoConverter.
|
||||
* DATAMONGO-2118 - Fix typo in repositories reference documentation.
|
||||
* DATAMONGO-2110 - Release 1.10.17 (Ingalls SR17).
|
||||
|
||||
|
||||
Changes in version 2.1.2.RELEASE (2018-10-29)
|
||||
---------------------------------------------
|
||||
* DATAMONGO-2118 - Fix typo in repositories reference documentation.
|
||||
* DATAMONGO-2113 - ChangeStreamTasks incorrectly converts resumeAt Instants into BsonTimestamp.
|
||||
* DATAMONGO-2107 - Release 2.1.2 (Lovelace SR2).
|
||||
* DATAMONGO-2098 - Typo in MappingMongoConverterParser.
|
||||
|
||||
|
||||
Changes in version 1.10.16.RELEASE (2018-10-15)
|
||||
-----------------------------------------------
|
||||
* DATAMONGO-2096 - Aggregation.graphLookup.**.connectFrom(String) does not handle nested field.
|
||||
* DATAMONGO-2083 - Release 1.10.16 (Ingalls SR16).
|
||||
|
||||
|
||||
Changes in version 2.0.11.RELEASE (2018-10-15)
|
||||
----------------------------------------------
|
||||
* DATAMONGO-2101 - NoSuchMethodException: org.springframework.data.mongodb.core.geo.GeoJsonPoint.<init>().
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Spring Data MongoDB 2.0.11
|
||||
Spring Data MongoDB 2.0.12
|
||||
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