Compare commits

...

13 Commits

Author SHA1 Message Date
Spring Buildmaster
a7c3ef2aa8 DATAMONGO-1033 - Release version 1.5.4.RELEASE (Dijkstra SR4). 2014-08-27 03:11:35 -07:00
Oliver Gierke
3320e49c0b DATAMONGO-1033 - Prepare 1.5.4.RELEASE (Dijkstra SR4). 2014-08-27 11:57:52 +02:00
Oliver Gierke
286efca52d DATAMONGO-1033 - Updated changelog. 2014-08-27 11:28:08 +02:00
Christoph Strobl
92926befc9 DATAMONGO-1038 - Assert Mongo instances cleaned up properly after test runs.
Add JUnit rule and RunListener taking care of clean up task.

Original pull request: #221.
2014-08-27 11:12:58 +02:00
Oliver Gierke
703f24ae1c DATAMONGO-1021 - Updated changelog. 2014-08-27 07:18:28 +02:00
Oliver Gierke
febe703954 DATAMONGO-1034 - Explicitly reject incompatible types in MappingMongoConverter.
Improved the exception message that is occurs if the source document contains a BasicDBList but has to be converted into a complex object. We now explicitly hint to use a custom Converter to manually.
2014-08-26 20:05:58 +02:00
Oliver Gierke
440d16ebc6 DATAMONGO-1030 - Projections now work on single-entity query method executions.
We now correctly forward the domain type collection to the query executing a query for a projection type.
2014-08-26 15:27:39 +02:00
Christoph Strobl
11c2e90736 DATAMONGO-1025 - Fix creation of nested named index.
We new prefix explicitly named indexes on nested types (eg. for embedded properties) with the path pointing to the property. This avoids errors having equally named index definitions on different paths pointing to the same type within one collection.

Along the way we harmonized index naming for geospatial index definitions where only the properties field name was taken into account where it should have been the full property path.

Original pull request: #219.
2014-08-26 15:23:59 +02:00
Thomas Darimont
816a567f29 DATAMONGO-1020 - LimitOperation is now a public class.
Original pull request: #218.
2014-08-12 12:32:21 +02:00
Oliver Gierke
e35486759b DATAMONGO-1008 - Polishing.
Slightly changed the implementation of the 2dsphere check, Minor refactorings in the test case.

Original pull request: #210.
2014-07-31 17:26:02 +02:00
Christoph Strobl
b80c81f861 DATAMONGO-1008 - DefaultIndexOperations no considers 2dsphere, too.
We now also check for 2dsphere when inspecting index keys and create an geo IndexField in that case.

Original pull request: #210.
2014-07-31 17:25:53 +02:00
Oliver Gierke
005d21c0b6 DATAMONGO-1007 - After release cleanups. 2014-07-28 12:29:37 +02:00
Spring Buildmaster
3c8b7a54d6 DATAMONGO-1007 - Prepare next development iteration. 2014-07-28 02:23:57 -07:00
25 changed files with 835 additions and 66 deletions

View File

@@ -5,7 +5,7 @@
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>1.5.2.RELEASE</version>
<version>1.5.4.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>1.4.2.RELEASE</version>
<version>1.4.4.RELEASE</version>
<relativePath>../spring-data-build/parent/pom.xml</relativePath>
</parent>
@@ -29,7 +29,7 @@
<properties>
<project.type>multi</project.type>
<dist.id>spring-data-mongodb</dist.id>
<springdata.commons>1.8.2.RELEASE</springdata.commons>
<springdata.commons>1.8.4.RELEASE</springdata.commons>
<mongo>2.12.1</mongo>
<mongo.osgi>2.12.1</mongo.osgi>
</properties>

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>1.5.2.RELEASE</version>
<version>1.5.4.RELEASE</version>
<relativePath>../pom.xml</relativePath>
</parent>
@@ -48,7 +48,7 @@
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>1.5.2.RELEASE</version>
<version>1.5.4.RELEASE</version>
</dependency>
<dependency>

View File

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

View File

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

View File

@@ -2,7 +2,7 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-data-mongodb</artifactId>
<name>Spring Data MongoDB - Core</name>
@@ -11,7 +11,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>1.5.2.RELEASE</version>
<version>1.5.4.RELEASE</version>
<relativePath>../pom.xml</relativePath>
</parent>
@@ -21,7 +21,7 @@
</properties>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
@@ -77,7 +77,7 @@
<version>1.0</version>
<optional>true</optional>
</dependency>
<!-- CDI -->
<dependency>
<groupId>javax.enterprise</groupId>
@@ -86,21 +86,21 @@
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>javax.el</groupId>
<artifactId>el-api</artifactId>
<version>${cdi}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.openwebbeans.test</groupId>
<artifactId>cditest-owb</artifactId>
<version>${webbeans}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
@@ -115,7 +115,7 @@
<version>${validation}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.objenesis</groupId>
<artifactId>objenesis</artifactId>
@@ -129,23 +129,23 @@
<version>4.2.0.Final</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>${jodatime}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>${slf4j}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
@@ -189,9 +189,14 @@
<systemPropertyVariables>
<java.util.logging.config.file>src/test/resources/logging.properties</java.util.logging.config.file>
</systemPropertyVariables>
<properties>
<property>
<name>listener</name>
<value>org.springframework.data.mongodb.test.util.CleanMongoDBJunitRunListener</value>
</property>
</properties>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -18,6 +18,8 @@ package org.springframework.data.mongodb.core;
import static org.springframework.data.domain.Sort.Direction.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import org.springframework.dao.DataAccessException;
@@ -41,6 +43,7 @@ public class DefaultIndexOperations implements IndexOperations {
private static final Double ONE = Double.valueOf(1);
private static final Double MINUS_ONE = Double.valueOf(-1);
private static final Collection<String> TWO_D_IDENTIFIERS = Arrays.asList("2d", "2dsphere");
private final MongoOperations mongoOperations;
private final String collectionName;
@@ -140,7 +143,7 @@ public class DefaultIndexOperations implements IndexOperations {
Object value = keyDbObject.get(key);
if ("2d".equals(value)) {
if (TWO_D_IDENTIFIERS.contains(value)) {
indexFields.add(IndexField.geo(key));
} else {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013 the original author or authors.
* Copyright 2013-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,7 +28,7 @@ import com.mongodb.DBObject;
* @author Oliver Gierke
* @since 1.3
*/
class LimitOperation implements AggregationOperation {
public class LimitOperation implements AggregationOperation {
private final long maxElements;

View File

@@ -76,6 +76,8 @@ import com.mongodb.DBRef;
*/
public class MappingMongoConverter extends AbstractMongoConverter implements ApplicationContextAware {
private static final String INCOMPATIBLE_TYPES = "Cannot convert %1$s of type %2$s into an instance of %3$s! Implement a custom Converter<%2$s, %3$s> and register it with the CustomConversions. Parent object was: %4$s";
protected static final Logger LOGGER = LoggerFactory.getLogger(MappingMongoConverter.class);
protected final MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
@@ -214,6 +216,10 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
return (S) readMap(typeToUse, dbo, parent);
}
if (dbo instanceof BasicDBList) {
throw new MappingException(String.format(INCOMPATIBLE_TYPES, dbo, BasicDBList.class, typeToUse.getType(), parent));
}
// Retrieve persistent entity info
MongoPersistentEntity<S> persistentEntity = (MongoPersistentEntity<S>) mappingContext
.getPersistentEntity(typeToUse);

View File

@@ -73,7 +73,43 @@ public @interface CompoundIndex {
boolean dropDups() default false;
/**
* The name of the index to be created.
* The name of the index to be created. <br />
* <br />
* The name will only be applied as is when defined on root level. For usage on nested or embedded structures the
* provided name will be prefixed with the path leading to the entity. <br />
* <br />
* The structure below
*
* <pre>
* <code>
* &#64;Document
* class Root {
* Hybrid hybrid;
* Nested nested;
* }
*
* &#64;Document
* &#64;CompoundIndex(name = "compound_index", def = "{'h1': 1, 'h2': 1}")
* class Hybrid {
* String h1, h2;
* }
*
* &#64;CompoundIndex(name = "compound_index", def = "{'n1': 1, 'n2': 1}")
* class Nested {
* String n1, n2;
* }
* </code>
* </pre>
*
* resolves in the following index structures
*
* <pre>
* <code>
* db.root.ensureIndex( { hybrid.h1: 1, hybrid.h2: 1 } , { name: "hybrid.compound_index" } )
* db.root.ensureIndex( { nested.n1: 1, nested.n2: 1 } , { name: "nested.compound_index" } )
* db.hybrid.ensureIndex( { h1: 1, h2: 1 } , { name: "compound_index" } )
* </code>
* </pre>
*
* @return
*/

View File

@@ -32,7 +32,41 @@ import java.lang.annotation.Target;
public @interface GeoSpatialIndexed {
/**
* Name of the property in the document that contains the [x, y] or radial coordinates to index.
* Index name. <br />
* <br />
* The name will only be applied as is when defined on root level. For usage on nested or embedded structures the
* provided name will be prefixed with the path leading to the entity. <br />
* <br />
* The structure below
*
* <pre>
* <code>
* &#64;Document
* class Root {
* Hybrid hybrid;
* Nested nested;
* }
*
* &#64;Document
* class Hybrid {
* &#64;GeoSpatialIndexed(name="index") Point h1;
* }
*
* class Nested {
* &#64;GeoSpatialIndexed(name="index") Point n1;
* }
* </code>
* </pre>
*
* resolves in the following index structures
*
* <pre>
* <code>
* db.root.ensureIndex( { hybrid.h1: "2d" } , { name: "hybrid.index" } )
* db.root.ensureIndex( { nested.n1: "2d" } , { name: "nested.index" } )
* db.hybrid.ensureIndex( { h1: "2d" } , { name: "index" } )
* </code>
* </pre>
*
* @return
*/

View File

@@ -58,7 +58,41 @@ public @interface Indexed {
boolean dropDups() default false;
/**
* Index name.
* Index name. <br />
* <br />
* The name will only be applied as is when defined on root level. For usage on nested or embedded structures the
* provided name will be prefixed with the path leading to the entity. <br />
* <br />
* The structure below
*
* <pre>
* <code>
* &#64;Document
* class Root {
* Hybrid hybrid;
* Nested nested;
* }
*
* &#64;Document
* class Hybrid {
* &#64;Indexed(name="index") String h1;
* }
*
* class Nested {
* &#64;Indexed(name="index") String n1;
* }
* </code>
* </pre>
*
* resolves in the following index structures
*
* <pre>
* <code>
* db.root.ensureIndex( { hybrid.h1: 1 } , { name: "hybrid.index" } )
* db.root.ensureIndex( { nested.n1: 1 } , { name: "nested.index" } )
* db.hybrid.ensureIndex( { h1: 1} , { name: "index" } )
* </code>
* </pre>
*
* @return
*/

View File

@@ -24,7 +24,6 @@ import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.domain.Sort;
import org.springframework.data.mapping.PropertyHandler;
@@ -92,7 +91,7 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
Assert.notNull(document, "Given entity is not collection root.");
final List<IndexDefinitionHolder> indexInformation = new ArrayList<MongoPersistentEntityIndexResolver.IndexDefinitionHolder>();
indexInformation.addAll(potentiallyCreateCompoundIndexDefinitions("", root.getCollection(), root.getType()));
indexInformation.addAll(potentiallyCreateCompoundIndexDefinitions("", root.getCollection(), root));
final CycleGuard guard = new CycleGuard();
@@ -133,10 +132,11 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
private List<IndexDefinitionHolder> resolveIndexForClass(final Class<?> type, final String path,
final String collection, final CycleGuard guard) {
final List<IndexDefinitionHolder> indexInformation = new ArrayList<MongoPersistentEntityIndexResolver.IndexDefinitionHolder>();
indexInformation.addAll(potentiallyCreateCompoundIndexDefinitions(path, collection, type));
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(type);
final List<IndexDefinitionHolder> indexInformation = new ArrayList<MongoPersistentEntityIndexResolver.IndexDefinitionHolder>();
indexInformation.addAll(potentiallyCreateCompoundIndexDefinitions(path, collection, entity));
entity.doWithProperties(new PropertyHandler<MongoPersistentProperty>() {
@Override
@@ -178,14 +178,13 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
}
private List<IndexDefinitionHolder> potentiallyCreateCompoundIndexDefinitions(String dotPath, String collection,
Class<?> type) {
MongoPersistentEntity<?> entity) {
if (AnnotationUtils.findAnnotation(type, CompoundIndexes.class) == null
&& AnnotationUtils.findAnnotation(type, CompoundIndex.class) == null) {
if (entity.findAnnotation(CompoundIndexes.class) == null && entity.findAnnotation(CompoundIndex.class) == null) {
return Collections.emptyList();
}
return createCompoundIndexDefinitions(dotPath, collection, type);
return createCompoundIndexDefinitions(dotPath, collection, entity);
}
/**
@@ -197,21 +196,21 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
* @return
*/
protected List<IndexDefinitionHolder> createCompoundIndexDefinitions(String dotPath, String fallbackCollection,
Class<?> type) {
MongoPersistentEntity<?> entity) {
List<IndexDefinitionHolder> indexDefinitions = new ArrayList<MongoPersistentEntityIndexResolver.IndexDefinitionHolder>();
CompoundIndexes indexes = AnnotationUtils.findAnnotation(type, CompoundIndexes.class);
CompoundIndexes indexes = entity.findAnnotation(CompoundIndexes.class);
if (indexes != null) {
for (CompoundIndex index : indexes.value()) {
indexDefinitions.add(createCompoundIndexDefinition(dotPath, fallbackCollection, index));
indexDefinitions.add(createCompoundIndexDefinition(dotPath, fallbackCollection, index, entity));
}
}
CompoundIndex index = AnnotationUtils.findAnnotation(type, CompoundIndex.class);
CompoundIndex index = entity.findAnnotation(CompoundIndex.class);
if (index != null) {
indexDefinitions.add(createCompoundIndexDefinition(dotPath, fallbackCollection, index));
indexDefinitions.add(createCompoundIndexDefinition(dotPath, fallbackCollection, index, entity));
}
return indexDefinitions;
@@ -219,13 +218,13 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
@SuppressWarnings("deprecation")
protected IndexDefinitionHolder createCompoundIndexDefinition(String dotPath, String fallbackCollection,
CompoundIndex index) {
CompoundIndex index, MongoPersistentEntity<?> entity) {
CompoundIndexDefinition indexDefinition = new CompoundIndexDefinition(resolveCompoundIndexKeyFromStringDefinition(
dotPath, index.def()));
if (!index.useGeneratedName()) {
indexDefinition.named(index.name());
indexDefinition.named(pathAwareIndexName(index.name(), dotPath, null));
}
if (index.unique()) {
@@ -296,7 +295,7 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
IndexDirection.ASCENDING.equals(index.direction()) ? Sort.Direction.ASC : Sort.Direction.DESC);
if (!index.useGeneratedName()) {
indexDefinition.named(StringUtils.hasText(index.name()) ? index.name() : dotPath);
indexDefinition.named(pathAwareIndexName(index.name(), dotPath, persitentProperty));
}
if (index.unique()) {
@@ -338,7 +337,7 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
indexDefinition.withMin(index.min()).withMax(index.max());
if (!index.useGeneratedName()) {
indexDefinition.named(StringUtils.hasText(index.name()) ? index.name() : persistentProperty.getName());
indexDefinition.named(pathAwareIndexName(index.name(), dotPath, persistentProperty));
}
indexDefinition.typed(index.type()).withBucketSize(index.bucketSize()).withAdditionalField(index.additionalField());
@@ -346,6 +345,23 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
return new IndexDefinitionHolder(dotPath, indexDefinition, collection);
}
private String pathAwareIndexName(String indexName, String dotPath, MongoPersistentProperty property) {
String nameToUse = StringUtils.hasText(indexName) ? indexName : "";
if (!StringUtils.hasText(dotPath) || (property != null && dotPath.equals(property.getFieldName()))) {
return StringUtils.hasText(nameToUse) ? nameToUse : dotPath;
}
if (StringUtils.hasText(dotPath)) {
nameToUse = StringUtils.hasText(nameToUse) ? (property != null ? dotPath.replace("." + property.getFieldName(),
"") : dotPath) + "." + nameToUse : dotPath;
}
return nameToUse;
}
/**
* {@link CycleGuard} holds information about properties and the paths for accessing those. This information is used
* to detect potential cycles within the references.

View File

@@ -284,7 +284,7 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
MongoEntityMetadata<?> metadata = method.getEntityInformation();
return countProjection ? operations.count(query, metadata.getJavaType()) : operations.findOne(query,
metadata.getJavaType());
metadata.getJavaType(), metadata.getCollectionName());
}
}

View File

@@ -0,0 +1,93 @@
/*
* Copyright 2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* 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,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.core;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.index.IndexInfo;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.util.ObjectUtils;
import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
/**
* Integration tests for {@link DefaultIndexOperations}.
*
* @author Christoph Strobl
* @author Oliver Gierke
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:infrastructure.xml")
public class DefaultIndexOperationsIntegrationTests {
static final DBObject GEO_SPHERE_2D = new BasicDBObject("loaction", "2dsphere");
@Autowired MongoTemplate template;
DefaultIndexOperations indexOps;
DBCollection collection;
@Before
public void setUp() {
String collectionName = this.template.getCollectionName(DefaultIndexOperationsIntegrationTestsSample.class);
this.collection = this.template.getDb().getCollection(collectionName);
this.collection.dropIndexes();
this.indexOps = new DefaultIndexOperations(template, collectionName);
}
/**
* @see DATAMONGO-1008
*/
@Test
public void getIndexInfoShouldBeAbleToRead2dsphereIndex() {
collection.createIndex(GEO_SPHERE_2D);
IndexInfo info = findAndReturnIndexInfo(GEO_SPHERE_2D);
assertThat(info.getIndexFields().get(0).isGeo(), is(true));
}
private IndexInfo findAndReturnIndexInfo(DBObject keys) {
return findAndReturnIndexInfo(indexOps.getIndexInfo(), keys);
}
@SuppressWarnings("deprecation")
private static IndexInfo findAndReturnIndexInfo(Iterable<IndexInfo> candidates, DBObject keys) {
return findAndReturnIndexInfo(candidates, DBCollection.genIndexName(keys));
}
private static IndexInfo findAndReturnIndexInfo(Iterable<IndexInfo> candidates, String name) {
for (IndexInfo info : candidates) {
if (ObjectUtils.nullSafeEquals(name, info.getName())) {
return info;
}
}
throw new AssertionError(String.format("Index with %s was not found", name));
}
static class DefaultIndexOperationsIntegrationTestsSample {}
}

View File

@@ -45,7 +45,9 @@ import org.hamcrest.Matchers;
import org.joda.time.LocalDate;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
@@ -99,6 +101,8 @@ public class MappingMongoConverterUnitTests {
@Mock ApplicationContext context;
@Mock DbRefResolver resolver;
public @Rule ExpectedException exception = ExpectedException.none();
@Before
public void setUp() {
@@ -1839,6 +1843,29 @@ public class MappingMongoConverterUnitTests {
verify(mock, times(1)).initialize();
}
/**
* @see DATAMONGO-1034
*/
@Test
public void rejectsBasicDbListToBeConvertedIntoComplexType() {
BasicDBList inner = new BasicDBList();
inner.add("key");
inner.add("value");
BasicDBList outer = new BasicDBList();
outer.add(inner);
outer.add(inner);
BasicDBObject source = new BasicDBObject("attributes", outer);
exception.expect(MappingException.class);
exception.expectMessage(Item.class.getName());
exception.expectMessage(BasicDBList.class.getName());
converter.read(Item.class, source);
}
static class GenericType<T> {
T content;
}

View File

@@ -163,8 +163,8 @@ public class MongoPersistentEntityIndexCreatorUnitTests {
new MongoPersistentEntityIndexCreator(mappingContext, factory);
assertThat(keysCaptor.getValue(), equalTo(new BasicDBObjectBuilder().add("company.address.location", "2d").get()));
assertThat(optionsCaptor.getValue(), equalTo(new BasicDBObjectBuilder().add("name", "location").add("min", -180)
.add("max", 180).add("bits", 26).get()));
assertThat(optionsCaptor.getValue(), equalTo(new BasicDBObjectBuilder().add("name", "company.address.location")
.add("min", -180).add("max", 180).add("bits", 26).get()));
}
/**

View File

@@ -576,6 +576,60 @@ public class MongoPersistentEntityIndexResolverUnitTests {
.resolveIndexForEntity(dummy);
}
/**
* @see DATAMONGO-1025
*/
@Test
public void shouldUsePathIndexAsIndexNameForDocumentsHavingNamedNestedCompoundIndexFixedOnCollection() {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(DocumentWithNestedDocumentHavingNamedCompoundIndex.class);
assertThat((String) indexDefinitions.get(0).getIndexOptions().get("name"),
equalTo("propertyOfTypeHavingNamedCompoundIndex.c_index"));
}
/**
* @see DATAMONGO-1025
*/
@Test
public void shouldUseIndexNameForNestedTypesWithNamedCompoundIndexDefinition() {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(DocumentWithNestedTypeHavingNamedCompoundIndex.class);
assertThat((String) indexDefinitions.get(0).getIndexOptions().get("name"),
equalTo("propertyOfTypeHavingNamedCompoundIndex.c_index"));
}
/**
* @see DATAMONGO-1025
*/
@Test
public void shouldUsePathIndexAsIndexNameForDocumentsHavingNamedNestedIndexFixedOnCollection() {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(DocumentWithNestedDocumentHavingNamedIndex.class);
assertThat((String) indexDefinitions.get(0).getIndexOptions().get("name"),
equalTo("propertyOfTypeHavingNamedIndex.property_index"));
}
/**
* @see DATAMONGO-1025
*/
@Test
public void shouldUseIndexNameForNestedTypesWithNamedIndexDefinition() {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(DocumentWithNestedTypeHavingNamedIndex.class);
assertThat((String) indexDefinitions.get(0).getIndexOptions().get("name"),
equalTo("propertyOfTypeHavingNamedIndex.property_index"));
}
/**
* @see DATAMONGO-1025
*/
@Test
public void shouldUseIndexNameOnRootLevel() {
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(DocumentWithNamedIndex.class);
assertThat((String) indexDefinitions.get(0).getIndexOptions().get("name"), equalTo("property_index"));
}
@Document
static class MixedIndexRoot {
@@ -668,6 +722,54 @@ public class MongoPersistentEntityIndexResolverUnitTests {
List<SelfCyclingViaCollectionType> cyclic;
}
@Document
@CompoundIndex(name = "c_index", def = "{ foo:1, bar:1 }")
static class DocumentWithNamedCompoundIndex {
String property;
}
@Document
static class DocumentWithNamedIndex {
@Indexed(name = "property_index") String property;
}
static class TypeWithNamedIndex {
@Indexed(name = "property_index") String property;
}
@Document
static class DocumentWithNestedDocumentHavingNamedCompoundIndex {
DocumentWithNamedCompoundIndex propertyOfTypeHavingNamedCompoundIndex;
}
@CompoundIndex(name = "c_index", def = "{ foo:1, bar:1 }")
static class TypeWithNamedCompoundIndex {
String property;
}
@Document
static class DocumentWithNestedTypeHavingNamedCompoundIndex {
TypeWithNamedCompoundIndex propertyOfTypeHavingNamedCompoundIndex;
}
@Document
static class DocumentWithNestedDocumentHavingNamedIndex {
DocumentWithNamedIndex propertyOfTypeHavingNamedIndex;
}
@Document
static class DocumentWithNestedTypeHavingNamedIndex {
TypeWithNamedIndex propertyOfTypeHavingNamedIndex;
}
}
private static List<IndexDefinitionHolder> prepareMappingContextAndResolveIndexForType(Class<?> type) {

View File

@@ -949,4 +949,18 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
public void shouldFindPersonsWhenUsingQueryDslPerdicatedOnIdProperty() {
assertThat(repository.findAll(person.id.in(Arrays.asList(dave.id, carter.id))), containsInAnyOrder(dave, carter));
}
/**
* @see DATAMONGO-1030
*/
@Test
public void executesSingleEntityQueryWithProjectionCorrectly() {
PersonSummary result = repository.findSummaryByLastname("Beauford");
assertThat(result, is(notNullValue()));
assertThat(result.firstname, is("Carter"));
assertThat(result.lastname, is("Beauford"));
}
}

View File

@@ -302,4 +302,9 @@ public interface PersonRepository extends MongoRepository<Person, String>, Query
*/
@Query("{lastname:?0, address.street:{$in:?1}}")
Page<Person> findByCustomQueryLastnameAndAddressStreetInList(String lastname, List<String> streetNames, Pageable page);
/**
* @see DATAMONGO-1030
*/
PersonSummary findSummaryByLastname(String lastname);
}

View File

@@ -0,0 +1,25 @@
/*
* Copyright 2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* 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,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.repository;
/**
* @author Oliver Gierke
*/
public class PersonSummary {
String firstname;
String lastname;
}

View File

@@ -0,0 +1,186 @@
/*
* Copyright 2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* 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,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.test.util;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
import com.mongodb.DB;
import com.mongodb.MongoClient;
/**
* @author Christoph Strobl
*/
public class CleanMongoDB implements TestRule {
private static final Logger LOGGER = LoggerFactory.getLogger(CleanMongoDB.class);
public enum Types {
DATABASE, COLLECTION, INDEX;
}
private Set<String> preserveDatabases = new HashSet<String>() {
private static final long serialVersionUID = -8698807376808700046L;
{
add("admin");
add("local");
}
};
private Set<String> dbNames = new HashSet<String>();
private Set<String> collectionNames = new HashSet<String>();
private Set<Types> types = new HashSet<CleanMongoDB.Types>();
private MongoClient client;
public CleanMongoDB() {
this(null);
}
public CleanMongoDB(String host, int port) throws UnknownHostException {
this(new MongoClient(host, port));
}
public CleanMongoDB(MongoClient client) {
this.client = client;
}
public static CleanMongoDB everything() {
CleanMongoDB cleanMongoDB = new CleanMongoDB();
cleanMongoDB.clean(Types.DATABASE);
return cleanMongoDB;
}
public static CleanMongoDB databases(String... dbNames) {
CleanMongoDB cleanMongoDB = new CleanMongoDB();
cleanMongoDB.clean(Types.DATABASE);
cleanMongoDB.collectionNames.addAll(Arrays.asList(dbNames));
return cleanMongoDB;
}
public static CleanMongoDB indexes() {
CleanMongoDB cleanMongoDB = new CleanMongoDB();
cleanMongoDB.clean(Types.INDEX);
return cleanMongoDB;
}
public CleanMongoDB clean(Types... types) {
this.types.addAll(Arrays.asList(types));
return this;
}
public Statement apply() {
return apply(null, null);
}
public Statement apply(Statement base, Description description) {
return new MongoCleanStatement(base);
}
private class MongoCleanStatement extends Statement {
private final Statement base;
public MongoCleanStatement(Statement base) {
this.base = base;
}
@Override
public void evaluate() throws Throwable {
if (base != null) {
base.evaluate();
}
boolean isInternal = false;
if (client == null) {
client = new MongoClient();
isInternal = true;
}
Collection<String> dbNamesToUse = dbNames;
if (dbNamesToUse.isEmpty()) {
dbNamesToUse = client.getDatabaseNames();
}
for (String dbName : dbNamesToUse) {
if (preserveDatabases.contains(dbName.toLowerCase())) {
continue;
}
if (types.contains(Types.DATABASE)) {
client.dropDatabase(dbName);
LOGGER.debug("Dropping DB '{}'. ", dbName);
}
if (types.contains(Types.COLLECTION)) {
DB db = client.getDB(dbName);
Collection<String> collectionsToUse = initCollectionNames(db);
for (String collectionName : collectionsToUse) {
if (db.collectionExists(collectionName)) {
db.getCollectionFromString(collectionName).drop();
LOGGER.debug("Dropping collection '{}' for DB '{}'. ", collectionName, dbName);
}
}
}
if (types.contains(Types.INDEX)) {
DB db = client.getDB(dbName);
Collection<String> collectionsToUse = initCollectionNames(db);
for (String collectionName : collectionsToUse) {
if (db.collectionExists(collectionName)) {
db.getCollectionFromString(collectionName).dropIndexes();
LOGGER.debug("Dropping indexes in collection '{}' for DB '{}'. ", collectionName, dbName);
}
}
}
}
if (isInternal) {
client.close();
client = null;
}
}
private Collection<String> initCollectionNames(DB db) {
Collection<String> collectionsToUse = collectionNames;
if (CollectionUtils.isEmpty(collectionsToUse)) {
collectionsToUse = db.getCollectionNames();
}
return collectionsToUse;
}
}
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright 2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* 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,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.test.util;
import org.junit.runner.Result;
import org.junit.runner.notification.RunListener;
import org.springframework.data.mongodb.test.util.CleanMongoDB.Types;
/**
* @author Christoph Strobl
*/
public class CleanMongoDBJunitRunListener extends RunListener {
@Override
public void testRunFinished(Result result) throws Exception {
super.testRunFinished(result);
try {
new CleanMongoDB().clean(Types.INDEX).apply().evaluate();
} catch (Throwable e) {
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,105 @@
/*
* Copyright 2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* 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,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.test.util;
import static org.mockito.Matchers.*;
import static org.mockito.Mockito.*;
import java.util.Arrays;
import java.util.Collections;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.Description;
import org.junit.runner.RunWith;
import org.junit.runners.model.Statement;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.data.mongodb.test.util.CleanMongoDB.Types;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.MongoClient;
/**
* @author Christoph Strobl
*/
@RunWith(MockitoJUnitRunner.class)
public class CleanMongoDBTests {
private CleanMongoDB cleaner;
private @Mock Statement baseStatementMock;
private @Mock Description descriptionMock;
private @Mock MongoClient mongoClientMock;
private @Mock DB db1mock;
private @Mock DB db2mock;
private @Mock DBCollection collection1mock;
@Before
public void setUp() {
when(mongoClientMock.getDatabaseNames()).thenReturn(Arrays.asList("admin", "db1", "db2"));
when(mongoClientMock.getDB(eq("db1"))).thenReturn(db1mock);
when(mongoClientMock.getDB(eq("db2"))).thenReturn(db2mock);
when(db1mock.collectionExists(anyString())).thenReturn(true);
when(db2mock.collectionExists(anyString())).thenReturn(true);
when(db1mock.getCollectionNames()).thenReturn(Collections.singleton("collection-1"));
when(db2mock.getCollectionNames()).thenReturn(Collections.<String> emptySet());
when(db1mock.getCollectionFromString(eq("collection-1"))).thenReturn(collection1mock);
cleaner = new CleanMongoDB(mongoClientMock);
}
@Test
public void preservesSystemCollectionsCorrectly() throws Throwable {
cleaner.clean(Types.DATABASE);
cleaner.apply(baseStatementMock, descriptionMock).evaluate();
verify(mongoClientMock, times(1)).dropDatabase(eq("db1"));
verify(mongoClientMock, times(1)).dropDatabase(eq("db2"));
verify(mongoClientMock, never()).dropDatabase(eq("admin"));
}
@Test
public void removesCollectionsCorrectly() throws Throwable {
cleaner.clean(Types.COLLECTION);
cleaner.apply(baseStatementMock, descriptionMock).evaluate();
verify(mongoClientMock, never()).dropDatabase(eq("db1"));
verify(mongoClientMock, never()).dropDatabase(eq("db2"));
verify(mongoClientMock, never()).dropDatabase(eq("admin"));
verify(collection1mock, times(1)).drop();
}
@Test
public void removesIndexesCorrectly() throws Throwable {
cleaner.clean(Types.INDEX);
cleaner.apply(baseStatementMock, descriptionMock).evaluate();
verify(mongoClientMock, never()).dropDatabase(eq("db1"));
verify(mongoClientMock, never()).dropDatabase(eq("db2"));
verify(mongoClientMock, never()).dropDatabase(eq("admin"));
verify(collection1mock, times(1)).dropIndexes();
}
}

View File

@@ -1,6 +1,47 @@
Spring Data MongoDB Changelog
=============================
Changes in version 1.5.4.RELEASE (2014-08-27)
---------------------------------------------
* DATAMONGO-1038 - Assert Mongo instances cleand up properly after test runs.
* DATAMONGO-1034 - Improve error message when trying to convert incompatible types.
* DATAMONGO-1033 - Release 1.5.4.
* DATAMONGO-1030 - Query methods retuning a single entity does not work with projecting types.
* DATAMONGO-1027 - Collection inherits complex index from embedded class/object.
* DATAMONGO-1025 - Duplicate index creation on embedded documents.
* DATAMONGO-1020 - LimitOperator should be a public class.
* DATAMONGO-1008 - IndexOperations fail, when "2dsphere" index is present.
Changes in version 1.6.0.RC1 (2014-08-13)
-----------------------------------------
* DATAMONGO-1024 - Upgrade to Java driver 2.12.3.
* DATAMONGO-1021 - Release 1.6 RC1.
* DATAMONGO-1020 - LimitOperator should be a public class.
* DATAMONGO-1019 - Correct examples in reference documentation.
* DATAMONGO-1017 - Add support for custom implementations in CDI repositories.
* DATAMONGO-1016 - Remove deprecations in geospatial area.
* DATAMONGO-1015 - Move to Asciidoctor for reference documentation.
* DATAMONGO-1012 - Proxies for lazy DBRefs with field access should have their id values resolved eagerly.
* DATAMONGO-1009 - Adapt to new multi-store configuration detection.
* DATAMONGO-1008 - IndexOperations fail, when "2dsphere" index is present.
* DATAMONGO-1005 - Improve cycle-detection for DbRef's.
* DATAMONGO-1002 - Update.toString(…) might throw exception.
* DATAMONGO-1001 - Can't save/update lazy load object.
* DATAMONGO-999 - Multiple Mongo Instances always have the same MongoOption Reference - MongoOptionsFactoryBean has a static instance of MongoOptions.
* DATAMONGO-996 - Pagination broken after introduction of the support for top/first.
* DATAMONGO-995 - Parameter binding in String-based query does not bind all parameters.
* DATAMONGO-993 - The system variables $$CURRENT and $$ROOT not handled correctly.
* DATAMONGO-992 - Entity can't be deserialized if @TypeAlias is used.
* DATAMONGO-991 - Adapt to deprecation removals in Spring Data Commons.
* DATAMONGO-989 - MatchOperation should accept CriteriaDefinition.
* DATAMONGO-987 - Problem with lazy loading in @DBRef when getting data using MongoTemplate.
* DATAMONGO-974 - synthetic field target's name is returned instead of the alias name.
* DATAMONGO-973 - Add support for deriving full text queries.
* DATAMONGO-957 - Add support for query modifiers.
* DATAMONGO-420 - Extra quotes being added to @Query values and fields.
Changes in version 1.5.2.RELEASE (2014-07-28)
---------------------------------------------
* DATAMONGO-1007 - Release 1.5.2.
@@ -444,7 +485,7 @@ Changes in version 1.2.2.GA (2013-07-19)
Changes in version 1.3.0.M1 (2013-06-04)
----------------------------------------
** Bug
* [DATAMONGO-571] - Spring Data for MongoDb doesn't save null values when @Version is added to domain class
* [DATAMONGO-571] - Spring Data for MongoDb doesn't save null values when @Version is added to domain class
* [DATAMONGO-612] - Fix PDF reference documentation name
* [DATAMONGO-613] - Images missing from reference documentation
* [DATAMONGO-617] - NullPointerException in MongoTemplate.initializeVersionProperty(…)
@@ -480,7 +521,7 @@ Changes in version 1.3.0.M1 (2013-06-04)
* [DATAMONGO-637] - Typo in Query.query(…)
* [DATAMONGO-651] - WriteResult not available from thrown Exception
* [DATAMONGO-652] - Add support for elemMatch and positional operator projections
* [DATAMONGO-656] - Potential NullPointerException when debugging in MongoTemplate
* [DATAMONGO-656] - Potential NullPointerException when debugging in MongoTemplate
* [DATAMONGO-657] - Allow to write Map value as DBRef
* [DATAMONGO-666] - Fix architecture inconsistency created by MongoDataIntegrityViolationException
* [DATAMONGO-680] - SimpleMongoRepository.exists(ID) improvement
@@ -502,7 +543,7 @@ Changes in version 1.3.0.M1 (2013-06-04)
Changes in version 1.2.1.GA (2013-04-17)
----------------------------------------
** Bug
* [DATAMONGO-571] - Spring Data for MongoDb doesn't save null values when @Version is added to domain class
* [DATAMONGO-571] - Spring Data for MongoDb doesn't save null values when @Version is added to domain class
* [DATAMONGO-612] - Fix PDF reference documentation name
* [DATAMONGO-613] - Images missing from reference documentation
* [DATAMONGO-617] - NullPointerException in MongoTemplate.initializeVersionProperty(…)
@@ -599,7 +640,7 @@ Changes in version 1.1.1.GA (2012-10-17)
Changes in version 1.1.0.GA (2012-10-10)
----------------------------------------
** Bug
* [DATAMONGO-523] - @TypeAlias annotation not used with AbstractMongoConfiguration
* [DATAMONGO-523] - @TypeAlias annotation not used with AbstractMongoConfiguration
* [DATAMONGO-527] - Criteria.equals(…) broken for complex criterias
* [DATAMONGO-530] - MongoMappingContext.setApplicationContext(…) does not invoke superclass method
* [DATAMONGO-531] - StackOverflowError when persisting Groovy beans
@@ -676,16 +717,16 @@ Changes in version 1.1.0.M2 (2012-24-07)
* [DATAMONGO-446] - Pageable query methods returning List are broken
* [DATAMONGO-447] - Removal of Documents fails in in debug mode for Documents with complex ids
* [DATAMONGO-450] - enabling DEBUG causes RuntimeException
* [DATAMONGO-454] - ServerAddressPropertyEditor fails if a hostname is unresolvable
* [DATAMONGO-454] - ServerAddressPropertyEditor fails if a hostname is unresolvable
* [DATAMONGO-458] - When reading back empty collections unmodifiable instances of Collections.emptyList/Set is returned.
* [DATAMONGO-462] - findAll() fails with NPE - discovering the root cause
* [DATAMONGO-465] - Mongo inserts document with "_id" as an integer but saves with "_id" as a string.
* [DATAMONGO-465] - Mongo inserts document with "_id" as an integer but saves with "_id" as a string.
* [DATAMONGO-467] - String @id field is not mapped to ObjectId when using QueryDSL ".id" path
* [DATAMONGO-469] - Query creation from method names using AND criteria does not work anymore
* [DATAMONGO-474] - Wrong property is used for Id mapping
* [DATAMONGO-475] - 'group' operation fails where query references non primitive property
* [DATAMONGO-480] - The WriteResultChecking is not used in case of insert or save of documents.
* [DATAMONGO-483] - @Indexed(unique=true, name="foo") puts name's value to the 'key' in the MongoDB
* [DATAMONGO-483] - @Indexed(unique=true, name="foo") puts name's value to the 'key' in the MongoDB
* [DATAMONGO-489] - ClassCastException when loading Map<String, String[]>
** Improvement
@@ -695,7 +736,7 @@ Changes in version 1.1.0.M2 (2012-24-07)
* [DATAMONGO-466] - QueryMapper shouldn't map id properties of nested classes
* [DATAMONGO-470] - Criteria and Query should have proper equals(…) and hashCode() method.
* [DATAMONGO-477] - Change upper bound of Google Guava package import to 13
* [DATAMONGO-482] - typo in documentation - 2 i's in usiing
* [DATAMONGO-482] - typo in documentation - 2 i's in usiing
* [DATAMONGO-486] - Polish namspace implementation
* [DATAMONGO-491] - Release 1.1.0.M2
@@ -715,13 +756,13 @@ Changes in version 1.0.3.RELEASE (2012-24-07)
* [DATAMONGO-474] - Wrong property is used for Id mapping
* [DATAMONGO-475] - 'group' operation fails where query references non primitive property
* [DATAMONGO-480] - The WriteResultChecking is not used in case of insert or save of documents.
* [DATAMONGO-483] - @Indexed(unique=true, name="foo") puts name's value to the 'key' in the MongoDB
* [DATAMONGO-483] - @Indexed(unique=true, name="foo") puts name's value to the 'key' in the MongoDB
* [DATAMONGO-489] - ClassCastException when loading Map<String, String[]>
** Improvement
* [DATAMONGO-466] - QueryMapper shouldn't map id properties of nested classes
* [DATAMONGO-470] - Criteria and Query should have proper equals(…) and hashCode() method.
* [DATAMONGO-482] - typo in documentation - 2 i's in usiing
* [DATAMONGO-482] - typo in documentation - 2 i's in usiing
** Task
* [DATAMONGO-492] - Release 1.0.3
@@ -745,7 +786,7 @@ Changes in version 1.0.2.RELEASE (2012-06-20)
* [DATAMONGO-446] - Pageable query methods returning List are broken
* [DATAMONGO-447] - Removal of Documents fails in in debug mode for Documents with complex ids
* [DATAMONGO-450] - enabling DEBUG causes RuntimeException
* [DATAMONGO-454] - ServerAddressPropertyEditor fails if a hostname is unresolvable
* [DATAMONGO-454] - ServerAddressPropertyEditor fails if a hostname is unresolvable
* [DATAMONGO-461] - MappedConstructor potentially throws NullPointerException
* [DATAMONGO-462] - findAll() fails with NPE - discovering the root cause
@@ -926,7 +967,7 @@ Changes in version 1.0.0.M5 MongoDB (2011-10-24)
* [DATAMONGO-282] - Cannot create a "range" query
* [DATAMONGO-284] - Execution of Querydsl query maps id incorrectly
* [DATAMONGO-285] - NPE in MappingMongoConverter.writeMapInternal when saving a Map<String,Object> with val instance of Collection
* [DATAMONGO-288] - querying same property multiple times produces incorrect query
* [DATAMONGO-288] - querying same property multiple times produces incorrect query
* [DATAMONGO-289] - AbstractMongoEventListener will never call onAfterLoad
* [DATAMONGO-294] - List elements nested in Map lose their type when persisted
@@ -955,7 +996,7 @@ Changes in version 1.0.0.M5 MongoDB (2011-10-24)
* [DATAMONGO-274] - Split up repository package according to the structure in Spring Data JPA
** Task
* [DATAMONGO-264] - Ensure Data Document examples work
* [DATAMONGO-264] - Ensure Data Document examples work
* [DATAMONGO-265] - Create new github repository for mongodb
* [DATAMONGO-266] - Create new github repository for CouchDB
* [DATAMONGO-297] - Prune project directory
@@ -988,7 +1029,7 @@ Changes in version 1.0.0.M4 MongoDB (2011-09-01)
* [DATADOC-228] - NullPointerException when persiting Map with null values
* [DATADOC-229] - When a parameterized List is used in the PersistentConstructor, conversion fail
* [DATADOC-231] - spring-data-mongodb does not work in an OSGi server because of unresolved dependencies
* [DATADOC-232] - mongodb allow to $inc many fields in one query, but Updat().inc(firs).inc(last) do only last inc
* [DATADOC-232] - mongodb allow to $inc many fields in one query, but Updat().inc(firs).inc(last) do only last inc
* [DATADOC-235] - Unable to map unstructured data
* [DATADOC-236] - Repository queries do not honour order defined in method name
* [DATADOC-237] - @Indexed annotation doesn't honor field name from @Field annotation
@@ -1002,7 +1043,7 @@ Changes in version 1.0.0.M4 MongoDB (2011-09-01)
** Improvement
* [DATADOC-32] - SimpleMongoConverter could support identifying Spring EL expressions in keys
* [DATADOC-63] - Converters to support use of a 'typeId' strategy to determine class to marshall/unmarshal from Mongo
* [DATADOC-63] - Converters to support use of a 'typeId' strategy to determine class to marshall/unmarshal from Mongo
* [DATADOC-166] - Check for null if various template CRUD methods
* [DATADOC-169] - Registering custom converters for a type requires treating the type as simple in mapping context
* [DATADOC-171] - IllegalArgumentException when persisting entity with BigDecimal field
@@ -1085,7 +1126,7 @@ Querying / Updating
* [DATADOC-146] - Advanced Regexp Queries
Mapping
* [DATADOC-95] - Can not save an object that has not had any of its properties set
* [DATADOC-95] - Can not save an object that has not had any of its properties set
* [DATADOC-97] - ID replacement not working correctly when using updateFirst/updateMulti
* [DATADOC-98] - Collection<Collection> or Object[][] doesn't save correctly
* [DATADOC-109] - Add MappingContext to MongoConverter interface
@@ -1136,10 +1177,10 @@ Mapping
* [DATADOC-33] - Introduce annotation to demarcate id field in a domain object
Repository
* [DATADOC-47, DATACMNS-17] - Adapted new metamodel API
* [DATADOC-47, DATACMNS-17] - Adapted new metamodel API
* [DATADOC-46] - Added support for 'In' and 'NotIn' keyword
* [DATADOC-49] - Fixed 'And' and 'Or' keywords
* [DATADOC-41] - Added support for executing QueryDsl predicates
* [DATADOC-41] - Added support for executing QueryDsl predicates
* [DATADOC-69] - Let repository namespace pickup the default mapping context bean and allow configuration
* [DATADOC-24] - Allow use of @Query annotation to define queries
* [DATADOC-34] - Create indexes for columns that are mentioned in query methods

View File

@@ -1,4 +1,4 @@
Spring Data MongoDB 1.5.2
Spring Data MongoDB 1.5.4
Copyright (c) [2010-2014] Pivotal Software, Inc.
This product is licensed to you under the Apache License, Version 2.0 (the "License").