Compare commits
12 Commits
1.5.0.RC1
...
1.5.0.RELE
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c7e65cbc40 | ||
|
|
b8e02efb04 | ||
|
|
c7f20fb836 | ||
|
|
28a0202ef4 | ||
|
|
164e947045 | ||
|
|
7e65c0c87d | ||
|
|
9c1f753f17 | ||
|
|
0f821eb52d | ||
|
|
e3aadd63ab | ||
|
|
aa06d520df | ||
|
|
4fa1d4ba97 | ||
|
|
ba9f11b345 |
@@ -26,7 +26,7 @@ Add the Maven dependency:
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb</artifactId>
|
||||
<version>1.4.1.RELEASE</version>
|
||||
<version>1.5.0.RELEASE</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
@@ -36,7 +36,7 @@ If you'd rather like the latest snapshots of the upcoming major version, use our
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb</artifactId>
|
||||
<version>1.5.0.BUILD-SNAPSHOT</version>
|
||||
<version>1.6.0.BUILD-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<repository>
|
||||
|
||||
10
pom.xml
10
pom.xml
@@ -5,7 +5,7 @@
|
||||
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>1.5.0.RC1</version>
|
||||
<version>1.5.0.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.0.RC1</version>
|
||||
<version>1.4.0.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.0.RC1</springdata.commons>
|
||||
<springdata.commons>1.8.0.RELEASE</springdata.commons>
|
||||
<mongo>2.12.1</mongo>
|
||||
</properties>
|
||||
|
||||
@@ -122,8 +122,8 @@
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-libs-milestone</id>
|
||||
<url>http://repo.spring.io/libs-milestone</url>
|
||||
<id>spring-libs-release</id>
|
||||
<url>http://repo.spring.io/libs-release</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>1.5.0.RC1</version>
|
||||
<version>1.5.0.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.0.RC1</version>
|
||||
<version>1.5.0.RELEASE</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>1.5.0.RC1</version>
|
||||
<version>1.5.0.RELEASE</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>1.5.0.RC1</version>
|
||||
<version>1.5.0.RELEASE</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>1.5.0.RC1</version>
|
||||
<version>1.5.0.RELEASE</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -228,11 +228,13 @@ public class MappingMongoConverterParser implements BeanDefinitionParser {
|
||||
String abbreviateFieldNames = element.getAttribute("abbreviate-field-names");
|
||||
String fieldNamingStrategy = element.getAttribute("field-naming-strategy-ref");
|
||||
|
||||
if (StringUtils.hasText(fieldNamingStrategy) && StringUtils.hasText(abbreviateFieldNames)) {
|
||||
boolean fieldNamingStrategyReferenced = StringUtils.hasText(fieldNamingStrategy);
|
||||
boolean abbreviationActivated = StringUtils.hasText(abbreviateFieldNames)
|
||||
&& Boolean.parseBoolean(abbreviateFieldNames);
|
||||
|
||||
context
|
||||
.error("Only one of the attributes abbreviate-field-names and field-naming-strategy-ref can be configured!",
|
||||
element);
|
||||
if (fieldNamingStrategyReferenced && abbreviationActivated) {
|
||||
context.error("Field name abbreviation cannot be activated if a field-naming-strategy-ref is configured!",
|
||||
element);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -240,7 +242,7 @@ public class MappingMongoConverterParser implements BeanDefinitionParser {
|
||||
|
||||
if ("true".equals(abbreviateFieldNames)) {
|
||||
value = new RootBeanDefinition(CamelCaseAbbreviatingFieldNamingStrategy.class);
|
||||
} else if (StringUtils.hasText(fieldNamingStrategy)) {
|
||||
} else if (fieldNamingStrategyReferenced) {
|
||||
value = new RuntimeBeanReference(fieldNamingStrategy);
|
||||
}
|
||||
|
||||
|
||||
@@ -36,11 +36,12 @@ public @interface CompoundIndex {
|
||||
|
||||
/**
|
||||
* The actual index definition in JSON format. The keys of the JSON document are the fields to be indexed, the values
|
||||
* define the index direction (1 for ascending, -1 for descending).
|
||||
* define the index direction (1 for ascending, -1 for descending). <br />
|
||||
* If left empty on nested document, the whole document will be indexed.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String def();
|
||||
String def() default "";
|
||||
|
||||
/**
|
||||
* It does not actually make sense to use that attribute as the direction has to be defined in the {@link #def()}
|
||||
|
||||
@@ -17,10 +17,17 @@ package org.springframework.data.mongodb.core.index;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
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;
|
||||
import org.springframework.data.mongodb.core.index.Index.Duplicates;
|
||||
@@ -31,6 +38,8 @@ import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.BasicDBObjectBuilder;
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.util.JSON;
|
||||
|
||||
@@ -45,6 +54,8 @@ import com.mongodb.util.JSON;
|
||||
*/
|
||||
public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(MongoPersistentEntityIndexResolver.class);
|
||||
|
||||
private final MongoMappingContext mappingContext;
|
||||
|
||||
/**
|
||||
@@ -85,6 +96,8 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
||||
final List<IndexDefinitionHolder> indexInformation = new ArrayList<MongoPersistentEntityIndexResolver.IndexDefinitionHolder>();
|
||||
indexInformation.addAll(potentiallyCreateCompoundIndexDefinitions("", root.getCollection(), root.getType()));
|
||||
|
||||
final CycleGuard guard = new CycleGuard();
|
||||
|
||||
root.doWithProperties(new PropertyHandler<MongoPersistentProperty>() {
|
||||
|
||||
@Override
|
||||
@@ -92,7 +105,7 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
||||
|
||||
if (persistentProperty.isEntity()) {
|
||||
indexInformation.addAll(resolveIndexForClass(persistentProperty.getActualType(),
|
||||
persistentProperty.getFieldName(), root.getCollection()));
|
||||
persistentProperty.getFieldName(), root.getCollection(), guard));
|
||||
}
|
||||
|
||||
IndexDefinitionHolder indexDefinitionHolder = createIndexDefinitionHolderForProperty(
|
||||
@@ -115,7 +128,8 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
||||
* @return List of {@link IndexDefinitionHolder} representing indexes for given type and its referenced property
|
||||
* types. Will never be {@code null}.
|
||||
*/
|
||||
private List<IndexDefinitionHolder> resolveIndexForClass(Class<?> type, final String path, final String collection) {
|
||||
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));
|
||||
@@ -127,9 +141,15 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
||||
public void doWithPersistentProperty(MongoPersistentProperty persistentProperty) {
|
||||
|
||||
String propertyDotPath = (StringUtils.hasText(path) ? path + "." : "") + persistentProperty.getFieldName();
|
||||
guard.protect(persistentProperty, path);
|
||||
|
||||
if (persistentProperty.isEntity()) {
|
||||
indexInformation.addAll(resolveIndexForClass(persistentProperty.getActualType(), propertyDotPath, collection));
|
||||
try {
|
||||
indexInformation.addAll(resolveIndexForClass(persistentProperty.getActualType(), propertyDotPath,
|
||||
collection, guard));
|
||||
} catch (CyclicPropertyReferenceException e) {
|
||||
LOGGER.warn(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
IndexDefinitionHolder indexDefinitionHolder = createIndexDefinitionHolderForProperty(propertyDotPath,
|
||||
@@ -158,7 +178,8 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
||||
private List<IndexDefinitionHolder> potentiallyCreateCompoundIndexDefinitions(String dotPath, String collection,
|
||||
Class<?> type) {
|
||||
|
||||
if (AnnotationUtils.findAnnotation(type, CompoundIndexes.class) == null) {
|
||||
if (AnnotationUtils.findAnnotation(type, CompoundIndexes.class) == null
|
||||
&& AnnotationUtils.findAnnotation(type, CompoundIndex.class) == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@@ -176,38 +197,77 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
||||
protected List<IndexDefinitionHolder> createCompoundIndexDefinitions(String dotPath, String fallbackCollection,
|
||||
Class<?> type) {
|
||||
|
||||
List<IndexDefinitionHolder> indexDefinitions = new ArrayList<MongoPersistentEntityIndexResolver.IndexDefinitionHolder>();
|
||||
CompoundIndexes indexes = AnnotationUtils.findAnnotation(type, CompoundIndexes.class);
|
||||
List<IndexDefinitionHolder> indexDefinitions = new ArrayList<MongoPersistentEntityIndexResolver.IndexDefinitionHolder>(
|
||||
indexes.value().length);
|
||||
|
||||
for (CompoundIndex index : indexes.value()) {
|
||||
if (indexes != null) {
|
||||
for (CompoundIndex index : indexes.value()) {
|
||||
indexDefinitions.add(createCompoundIndexDefinition(dotPath, fallbackCollection, index));
|
||||
}
|
||||
}
|
||||
|
||||
String path = StringUtils.hasText(index.name()) ? index.name() : dotPath;
|
||||
String collection = StringUtils.hasText(index.collection()) ? index.collection() : fallbackCollection;
|
||||
CompoundIndex index = AnnotationUtils.findAnnotation(type, CompoundIndex.class);
|
||||
|
||||
CompoundIndexDefinition indexDefinition = new CompoundIndexDefinition((DBObject) JSON.parse(index.def()));
|
||||
if (!index.useGeneratedName()) {
|
||||
indexDefinition.named(index.name());
|
||||
}
|
||||
if (index.unique()) {
|
||||
indexDefinition.unique(index.dropDups() ? Duplicates.DROP : Duplicates.RETAIN);
|
||||
}
|
||||
if (index.sparse()) {
|
||||
indexDefinition.sparse();
|
||||
}
|
||||
if (index.background()) {
|
||||
indexDefinition.background();
|
||||
}
|
||||
if (index.expireAfterSeconds() >= 0) {
|
||||
indexDefinition.expire(index.expireAfterSeconds(), TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
indexDefinitions.add(new IndexDefinitionHolder(path, indexDefinition, collection));
|
||||
if (index != null) {
|
||||
indexDefinitions.add(createCompoundIndexDefinition(dotPath, fallbackCollection, index));
|
||||
}
|
||||
|
||||
return indexDefinitions;
|
||||
}
|
||||
|
||||
protected IndexDefinitionHolder createCompoundIndexDefinition(String dotPath, String fallbackCollection,
|
||||
CompoundIndex index) {
|
||||
|
||||
CompoundIndexDefinition indexDefinition = new CompoundIndexDefinition(resolveCompoundIndexKeyFromStringDefinition(
|
||||
dotPath, index.def()));
|
||||
|
||||
if (!index.useGeneratedName()) {
|
||||
indexDefinition.named(index.name());
|
||||
}
|
||||
|
||||
if (index.unique()) {
|
||||
indexDefinition.unique(index.dropDups() ? Duplicates.DROP : Duplicates.RETAIN);
|
||||
}
|
||||
|
||||
if (index.sparse()) {
|
||||
indexDefinition.sparse();
|
||||
}
|
||||
|
||||
if (index.background()) {
|
||||
indexDefinition.background();
|
||||
}
|
||||
|
||||
if (index.expireAfterSeconds() >= 0) {
|
||||
indexDefinition.expire(index.expireAfterSeconds(), TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
String collection = StringUtils.hasText(index.collection()) ? index.collection() : fallbackCollection;
|
||||
return new IndexDefinitionHolder(dotPath, indexDefinition, collection);
|
||||
}
|
||||
|
||||
private DBObject resolveCompoundIndexKeyFromStringDefinition(String dotPath, String keyDefinitionString) {
|
||||
|
||||
if (!StringUtils.hasText(dotPath) && !StringUtils.hasText(keyDefinitionString)) {
|
||||
throw new InvalidDataAccessApiUsageException("Cannot create index on root level for empty keys.");
|
||||
}
|
||||
|
||||
if (!StringUtils.hasText(keyDefinitionString)) {
|
||||
return new BasicDBObject(dotPath, 1);
|
||||
}
|
||||
|
||||
DBObject dbo = (DBObject) JSON.parse(keyDefinitionString);
|
||||
if (!StringUtils.hasText(dotPath)) {
|
||||
return dbo;
|
||||
}
|
||||
|
||||
BasicDBObjectBuilder dboBuilder = new BasicDBObjectBuilder();
|
||||
|
||||
for (String key : dbo.keySet()) {
|
||||
dboBuilder.add(dotPath + "." + key, dbo.get(key));
|
||||
}
|
||||
return dboBuilder.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates {@link IndexDefinition} wrapped in {@link IndexDefinitionHolder} out of {@link Indexed} for given
|
||||
* {@link MongoPersistentProperty}.
|
||||
@@ -223,24 +283,25 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
||||
Indexed index = persitentProperty.findAnnotation(Indexed.class);
|
||||
String collection = StringUtils.hasText(index.collection()) ? index.collection() : fallbackCollection;
|
||||
|
||||
Index indexDefinition = new Index();
|
||||
Index indexDefinition = new Index().on(dotPath,
|
||||
IndexDirection.ASCENDING.equals(index.direction()) ? Sort.Direction.ASC : Sort.Direction.DESC);
|
||||
|
||||
if (!index.useGeneratedName()) {
|
||||
indexDefinition.named(StringUtils.hasText(index.name()) ? index.name() : persitentProperty.getFieldName());
|
||||
indexDefinition.named(StringUtils.hasText(index.name()) ? index.name() : dotPath);
|
||||
}
|
||||
|
||||
indexDefinition.on(persitentProperty.getFieldName(),
|
||||
IndexDirection.ASCENDING.equals(index.direction()) ? Sort.Direction.ASC : Sort.Direction.DESC);
|
||||
|
||||
if (index.unique()) {
|
||||
indexDefinition.unique(index.dropDups() ? Duplicates.DROP : Duplicates.RETAIN);
|
||||
}
|
||||
|
||||
if (index.sparse()) {
|
||||
indexDefinition.sparse();
|
||||
}
|
||||
|
||||
if (index.background()) {
|
||||
indexDefinition.background();
|
||||
}
|
||||
|
||||
if (index.expireAfterSeconds() >= 0) {
|
||||
indexDefinition.expire(index.expireAfterSeconds(), TimeUnit.SECONDS);
|
||||
}
|
||||
@@ -276,6 +337,115 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
||||
return new IndexDefinitionHolder(dotPath, indexDefinition, collection);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link CycleGuard} holds information about properties and the paths for accessing those. This information is used
|
||||
* to detect potential cycles within the references.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
private static class CycleGuard {
|
||||
|
||||
private final Map<String, List<Path>> propertyTypeMap;
|
||||
|
||||
CycleGuard() {
|
||||
this.propertyTypeMap = new LinkedHashMap<String, List<Path>>();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param property The property to inspect
|
||||
* @param path The path under which the property can be reached.
|
||||
* @throws CyclicPropertyReferenceException in case a potential cycle is detected.
|
||||
*/
|
||||
void protect(MongoPersistentProperty property, String path) throws CyclicPropertyReferenceException {
|
||||
|
||||
String propertyTypeKey = createMapKey(property);
|
||||
if (propertyTypeMap.containsKey(propertyTypeKey)) {
|
||||
|
||||
List<Path> paths = propertyTypeMap.get(propertyTypeKey);
|
||||
|
||||
for (Path existingPath : paths) {
|
||||
|
||||
if (existingPath.cycles(property)) {
|
||||
paths.add(new Path(property, path));
|
||||
throw new CyclicPropertyReferenceException(property.getFieldName(), property.getOwner().getType(),
|
||||
existingPath.getPath());
|
||||
}
|
||||
}
|
||||
|
||||
paths.add(new Path(property, path));
|
||||
|
||||
} else {
|
||||
|
||||
ArrayList<Path> paths = new ArrayList<Path>();
|
||||
paths.add(new Path(property, path));
|
||||
propertyTypeMap.put(propertyTypeKey, paths);
|
||||
}
|
||||
}
|
||||
|
||||
private String createMapKey(MongoPersistentProperty property) {
|
||||
return property.getOwner().getType().getSimpleName() + ":" + property.getFieldName();
|
||||
}
|
||||
|
||||
private static class Path {
|
||||
|
||||
private final MongoPersistentProperty property;
|
||||
private final String path;
|
||||
|
||||
Path(MongoPersistentProperty property, String path) {
|
||||
|
||||
this.property = property;
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
boolean cycles(MongoPersistentProperty property) {
|
||||
|
||||
Pattern pattern = Pattern.compile("\\p{Punct}?" + Pattern.quote(property.getFieldName()) + "(\\p{Punct}|\\w)?");
|
||||
Matcher matcher = pattern.matcher(path);
|
||||
|
||||
int count = 0;
|
||||
while (matcher.find()) {
|
||||
count++;
|
||||
}
|
||||
|
||||
return count >= 1 && property.getOwner().getType().equals(this.property.getOwner().getType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 1.5
|
||||
*/
|
||||
public static class CyclicPropertyReferenceException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = -3762979307658772277L;
|
||||
|
||||
private final String propertyName;
|
||||
private final Class<?> type;
|
||||
private final String dotPath;
|
||||
|
||||
public CyclicPropertyReferenceException(String propertyName, Class<?> type, String dotPath) {
|
||||
|
||||
this.propertyName = propertyName;
|
||||
this.type = type;
|
||||
this.dotPath = dotPath;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Throwable#getMessage()
|
||||
*/
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return String.format("Found cycle for field '%s' in type '%s' for path '%s'", propertyName, type.getSimpleName(),
|
||||
dotPath);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of {@link IndexDefinition} holding additional (property)path information used for creating the
|
||||
* index. The path itself is the properties {@literal "dot"} path representation from its root document.
|
||||
@@ -285,9 +455,9 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
||||
*/
|
||||
public static class IndexDefinitionHolder implements IndexDefinition {
|
||||
|
||||
private String path;
|
||||
private IndexDefinition indexDefinition;
|
||||
private String collection;
|
||||
private final String path;
|
||||
private final IndexDefinition indexDefinition;
|
||||
private final String collection;
|
||||
|
||||
/**
|
||||
* Create
|
||||
@@ -306,7 +476,7 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@liteal "dot"} path used to create the index.
|
||||
* Get the {@literal "dot"} path used to create the index.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
|
||||
@@ -212,11 +212,11 @@ The base package in which to scan for entities annotated with @Document
|
||||
<xsd:union memberTypes="xsd:boolean xsd:string"/>
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="abbreviate-field-names" use="optional" default="false">
|
||||
<xsd:attribute name="abbreviate-field-names" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="org.springframework.data.mongodb.core.mapping.CamelCaseAbbreviatingFieldNamingStrategy">
|
||||
Enables abbreviating the field names for domain class properties to the
|
||||
first character of their camel case names, e.g. fooBar -> fb.
|
||||
first character of their camel case names, e.g. fooBar -> fb. Defaults to false.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
@@ -226,7 +226,7 @@ The base package in which to scan for entities annotated with @Document
|
||||
<xsd:attribute name="field-naming-strategy-ref" type="fieldNamingStrategyRef" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="org.springframework.data.mongodb.core.mapping.FieldNamingStrategy">
|
||||
The reference to a MappingContext. Will default to 'mappingContext'.
|
||||
The reference to a FieldNamingStrategy.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
@@ -654,4 +654,4 @@ The GridFs bucket string.]]></xsd:documentation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
</xsd:schema>
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanReference;
|
||||
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
@@ -49,6 +50,7 @@ import com.mongodb.DBObject;
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Darimont
|
||||
* @author Christoph Strobl
|
||||
* @author Ryan Tenney
|
||||
*/
|
||||
public class MappingMongoConverterParserIntegrationTests {
|
||||
|
||||
@@ -114,7 +116,7 @@ public class MappingMongoConverterParserIntegrationTests {
|
||||
public void rejectsInvalidFieldNamingStrategyConfiguration() {
|
||||
|
||||
exception.expect(BeanDefinitionParsingException.class);
|
||||
exception.expectMessage("abbreviate-field-names");
|
||||
exception.expectMessage("abbreviation");
|
||||
exception.expectMessage("field-naming-strategy-ref");
|
||||
|
||||
BeanDefinitionRegistry factory = new DefaultListableBeanFactory();
|
||||
@@ -134,6 +136,22 @@ public class MappingMongoConverterParserIntegrationTests {
|
||||
loadNestedBeanConfiguration();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-925, DATAMONGO-928
|
||||
*/
|
||||
@Test
|
||||
public void shouldSupportCustomFieldNamingStrategy() {
|
||||
assertStrategyReferenceSetFor("mappingConverterWithCustomFieldNamingStrategy");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-925, DATAMONGO-928
|
||||
*/
|
||||
@Test
|
||||
public void shouldNotFailLoadingConfigIfAbbreviationIsDisabledAndStrategySet() {
|
||||
assertStrategyReferenceSetFor("mappingConverterWithCustomFieldNamingStrategyAndAbbreviationDisabled");
|
||||
}
|
||||
|
||||
private void loadValidConfiguration() {
|
||||
this.loadConfiguration("namespace/converter.xml");
|
||||
}
|
||||
@@ -148,6 +166,19 @@ public class MappingMongoConverterParserIntegrationTests {
|
||||
reader.loadBeanDefinitions(new ClassPathResource(configLocation));
|
||||
}
|
||||
|
||||
private static void assertStrategyReferenceSetFor(String beanId) {
|
||||
|
||||
BeanDefinitionRegistry factory = new DefaultListableBeanFactory();
|
||||
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
|
||||
reader.loadBeanDefinitions(new ClassPathResource("namespace/converter-custom-fieldnamingstrategy.xml"));
|
||||
|
||||
BeanDefinition definition = reader.getRegistry().getBeanDefinition(beanId.concat(".mongoMappingContext"));
|
||||
BeanReference value = (BeanReference) definition.getPropertyValues().getPropertyValue("fieldNamingStrategy")
|
||||
.getValue();
|
||||
|
||||
assertThat(value.getBeanName(), is("customFieldNamingStrategy"));
|
||||
}
|
||||
|
||||
@Component
|
||||
public static class SampleConverter implements Converter<Person, DBObject> {
|
||||
public DBObject convert(Person source) {
|
||||
|
||||
@@ -34,6 +34,8 @@ import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.domain.Sort.Direction;
|
||||
import org.springframework.data.mongodb.MongoDbFactory;
|
||||
import org.springframework.data.mongodb.core.DBObjectTestUtils;
|
||||
import org.springframework.data.mongodb.core.Person;
|
||||
@@ -49,6 +51,7 @@ import org.springframework.data.mongodb.core.query.Query;
|
||||
|
||||
import com.mongodb.BasicDBList;
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.BasicDBObjectBuilder;
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.QueryBuilder;
|
||||
|
||||
@@ -586,6 +589,17 @@ public class QueryMapperUnitTests {
|
||||
assertThat(dbo.toString(), equalTo("{ \"embedded\" : { \"$in\" : [ { \"_id\" : \"1\"} , { \"_id\" : \"2\"}]}}"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-647
|
||||
*/
|
||||
@Test
|
||||
public void customizedFieldNameShouldBeMappedCorrectlyWhenApplyingSort() {
|
||||
|
||||
Query query = query(where("field").is("bar")).with(new Sort(Direction.DESC, "field"));
|
||||
DBObject dbo = mapper.getMappedObject(query.getSortObject(), context.getPersistentEntity(CustomizedField.class));
|
||||
assertThat(dbo, equalTo(new BasicDBObjectBuilder().add("foo", -1).get()));
|
||||
}
|
||||
|
||||
@Document
|
||||
public class Foo {
|
||||
@Id private ObjectId id;
|
||||
|
||||
@@ -17,6 +17,7 @@ package org.springframework.data.mongodb.core.index;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
@@ -27,7 +28,6 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.data.geo.Point;
|
||||
@@ -72,10 +72,10 @@ public class MongoPersistentEntityIndexCreatorUnitTests {
|
||||
optionsCaptor = ArgumentCaptor.forClass(DBObject.class);
|
||||
collectionCaptor = ArgumentCaptor.forClass(String.class);
|
||||
|
||||
Mockito.when(factory.getDb()).thenReturn(db);
|
||||
Mockito.when(db.getCollection(collectionCaptor.capture())).thenReturn(collection);
|
||||
when(factory.getDb()).thenReturn(db);
|
||||
when(db.getCollection(collectionCaptor.capture())).thenReturn(collection);
|
||||
|
||||
Mockito.doNothing().when(collection).createIndex(keysCaptor.capture(), optionsCaptor.capture());
|
||||
doNothing().when(collection).createIndex(keysCaptor.capture(), optionsCaptor.capture());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -106,7 +106,7 @@ public class MongoPersistentEntityIndexCreatorUnitTests {
|
||||
|
||||
creator.onApplicationEvent(event);
|
||||
|
||||
Mockito.verifyZeroInteractions(collection);
|
||||
verifyZeroInteractions(collection);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -181,6 +181,36 @@ public class MongoPersistentEntityIndexCreatorUnitTests {
|
||||
assertThat(optionsCaptor.getValue(), is(new BasicDBObjectBuilder().get()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-367
|
||||
*/
|
||||
@Test
|
||||
public void indexCreationShouldNotCreateNewCollectionForNestedGeoSpatialIndexStructures() {
|
||||
|
||||
MongoMappingContext mappingContext = prepareMappingContext(Wrapper.class);
|
||||
new MongoPersistentEntityIndexCreator(mappingContext, factory);
|
||||
|
||||
ArgumentCaptor<String> collectionNameCapturer = ArgumentCaptor.forClass(String.class);
|
||||
|
||||
verify(db, times(1)).getCollection(collectionNameCapturer.capture());
|
||||
assertThat(collectionNameCapturer.getValue(), equalTo("wrapper"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-367
|
||||
*/
|
||||
@Test
|
||||
public void indexCreationShouldNotCreateNewCollectionForNestedIndexStructures() {
|
||||
|
||||
MongoMappingContext mappingContext = prepareMappingContext(IndexedDocumentWrapper.class);
|
||||
new MongoPersistentEntityIndexCreator(mappingContext, factory);
|
||||
|
||||
ArgumentCaptor<String> collectionNameCapturer = ArgumentCaptor.forClass(String.class);
|
||||
|
||||
verify(db, times(1)).getCollection(collectionNameCapturer.capture());
|
||||
assertThat(collectionNameCapturer.getValue(), equalTo("indexedDocumentWrapper"));
|
||||
}
|
||||
|
||||
private static MongoMappingContext prepareMappingContext(Class<?> type) {
|
||||
|
||||
MongoMappingContext mappingContext = new MongoMappingContext();
|
||||
@@ -233,6 +263,17 @@ public class MongoPersistentEntityIndexCreatorUnitTests {
|
||||
@GeoSpatialIndexed Point location;
|
||||
}
|
||||
|
||||
@Document
|
||||
static class IndexedDocumentWrapper {
|
||||
|
||||
IndexedDocument indexedDocument;
|
||||
}
|
||||
|
||||
static class IndexedDocument {
|
||||
|
||||
@Indexed String indexedValue;
|
||||
}
|
||||
|
||||
@Document
|
||||
class EntityWithGeneratedIndexName {
|
||||
|
||||
|
||||
@@ -277,7 +277,7 @@ public class MongoPersistentEntityIndexResolverUnitTests {
|
||||
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(CompoundIndexOnLevelZero.class);
|
||||
|
||||
assertThat(indexDefinitions, hasSize(1));
|
||||
assertIndexPathAndCollection("compound_index", "CompoundIndexOnLevelZero", indexDefinitions.get(0));
|
||||
assertIndexPathAndCollection(new String[] { "foo", "bar" }, "CompoundIndexOnLevelZero", indexDefinitions.get(0));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -324,7 +324,56 @@ public class MongoPersistentEntityIndexResolverUnitTests {
|
||||
equalTo(new BasicDBObjectBuilder().add("unique", true).add("dropDups", true).add("sparse", true)
|
||||
.add("background", true).add("expireAfterSeconds", 10L).get()));
|
||||
assertThat(indexDefinition.getIndexKeys(), equalTo(new BasicDBObjectBuilder().add("foo", 1).add("bar", -1).get()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-929
|
||||
*/
|
||||
@Test
|
||||
public void compoundIndexPathOnLevelOneIsResolvedCorrectly() {
|
||||
|
||||
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(CompoundIndexOnLevelOne.class);
|
||||
|
||||
assertThat(indexDefinitions, hasSize(1));
|
||||
assertIndexPathAndCollection(new String[] { "zero.foo", "zero.bar" }, "CompoundIndexOnLevelOne",
|
||||
indexDefinitions.get(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-929
|
||||
*/
|
||||
@Test
|
||||
public void emptyCompoundIndexPathOnLevelOneIsResolvedCorrectly() {
|
||||
|
||||
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(CompoundIndexOnLevelOneWithEmptyIndexDefinition.class);
|
||||
|
||||
assertThat(indexDefinitions, hasSize(1));
|
||||
assertIndexPathAndCollection(new String[] { "zero" }, "CompoundIndexOnLevelZeroWithEmptyIndexDef",
|
||||
indexDefinitions.get(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-929
|
||||
*/
|
||||
@Test
|
||||
public void singleCompoundIndexPathOnLevelZeroIsResolvedCorrectly() {
|
||||
|
||||
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(SingleCompoundIndex.class);
|
||||
|
||||
assertThat(indexDefinitions, hasSize(1));
|
||||
assertIndexPathAndCollection(new String[] { "foo", "bar" }, "CompoundIndexOnLevelZero", indexDefinitions.get(0));
|
||||
}
|
||||
|
||||
@Document(collection = "CompoundIndexOnLevelOne")
|
||||
static class CompoundIndexOnLevelOne {
|
||||
|
||||
CompoundIndexOnLevelZero zero;
|
||||
}
|
||||
|
||||
@Document(collection = "CompoundIndexOnLevelZeroWithEmptyIndexDef")
|
||||
static class CompoundIndexOnLevelOneWithEmptyIndexDefinition {
|
||||
|
||||
CompoundIndexOnLevelZeroWithEmptyIndexDef zero;
|
||||
}
|
||||
|
||||
@Document(collection = "CompoundIndexOnLevelZero")
|
||||
@@ -332,6 +381,15 @@ public class MongoPersistentEntityIndexResolverUnitTests {
|
||||
dropDups = true, expireAfterSeconds = 10, sparse = true, unique = true) })
|
||||
static class CompoundIndexOnLevelZero {}
|
||||
|
||||
@CompoundIndexes({ @CompoundIndex(name = "compound_index", background = true, dropDups = true,
|
||||
expireAfterSeconds = 10, sparse = true, unique = true) })
|
||||
static class CompoundIndexOnLevelZeroWithEmptyIndexDef {}
|
||||
|
||||
@Document(collection = "CompoundIndexOnLevelZero")
|
||||
@CompoundIndex(name = "compound_index", def = "{'foo': 1, 'bar': -1}", background = true, dropDups = true,
|
||||
expireAfterSeconds = 10, sparse = true, unique = true)
|
||||
static class SingleCompoundIndex {}
|
||||
|
||||
static class IndexDefinedOnSuperClass extends CompoundIndexOnLevelZero {
|
||||
|
||||
}
|
||||
@@ -381,6 +439,55 @@ public class MongoPersistentEntityIndexResolverUnitTests {
|
||||
assertThat(indexDefinitions, empty());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-926
|
||||
*/
|
||||
@Test
|
||||
public void shouldNotRunIntoStackOverflow() {
|
||||
|
||||
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(CycleStartingInBetween.class);
|
||||
assertThat(indexDefinitions, hasSize(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-926
|
||||
*/
|
||||
@Test
|
||||
public void indexShouldBeFoundEvenForCyclePropertyReferenceOnLevelZero() {
|
||||
|
||||
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(CycleLevelZero.class);
|
||||
assertIndexPathAndCollection("indexedProperty", "cycleLevelZero", indexDefinitions.get(0));
|
||||
assertIndexPathAndCollection("cyclicReference.indexedProperty", "cycleLevelZero", indexDefinitions.get(1));
|
||||
assertThat(indexDefinitions, hasSize(2));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-926
|
||||
*/
|
||||
@Test
|
||||
public void indexShouldBeFoundEvenForCyclePropertyReferenceOnLevelOne() {
|
||||
|
||||
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(CycleOnLevelOne.class);
|
||||
assertIndexPathAndCollection("reference.indexedProperty", "cycleOnLevelOne", indexDefinitions.get(0));
|
||||
assertIndexPathAndCollection("reference.cyclicReference.reference.indexedProperty", "cycleOnLevelOne",
|
||||
indexDefinitions.get(1));
|
||||
assertThat(indexDefinitions, hasSize(2));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-926
|
||||
*/
|
||||
@Test
|
||||
public void indexBeResolvedCorrectlyWhenPropertiesOfDifferentTypesAreNamedEqually() {
|
||||
|
||||
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(NoCycleButIdenticallyNamedProperties.class);
|
||||
assertIndexPathAndCollection("foo", "noCycleButIdenticallyNamedProperties", indexDefinitions.get(0));
|
||||
assertIndexPathAndCollection("reference.foo", "noCycleButIdenticallyNamedProperties", indexDefinitions.get(1));
|
||||
assertIndexPathAndCollection("reference.deep.foo", "noCycleButIdenticallyNamedProperties",
|
||||
indexDefinitions.get(2));
|
||||
assertThat(indexDefinitions, hasSize(3));
|
||||
}
|
||||
|
||||
@Document
|
||||
static class MixedIndexRoot {
|
||||
|
||||
@@ -405,6 +512,48 @@ public class MongoPersistentEntityIndexResolverUnitTests {
|
||||
@Indexed Outer outer;
|
||||
}
|
||||
|
||||
@Document
|
||||
static class CycleLevelZero {
|
||||
|
||||
@Indexed String indexedProperty;
|
||||
CycleLevelZero cyclicReference;
|
||||
}
|
||||
|
||||
@Document
|
||||
static class CycleOnLevelOne {
|
||||
|
||||
CycleOnLevelOneReferenced reference;
|
||||
}
|
||||
|
||||
static class CycleOnLevelOneReferenced {
|
||||
|
||||
@Indexed String indexedProperty;
|
||||
CycleOnLevelOne cyclicReference;
|
||||
}
|
||||
|
||||
@Document
|
||||
public static class CycleStartingInBetween {
|
||||
|
||||
CycleOnLevelOne referenceToCycleStart;
|
||||
}
|
||||
|
||||
@Document
|
||||
static class NoCycleButIdenticallyNamedProperties {
|
||||
|
||||
@Indexed String foo;
|
||||
NoCycleButIdenticallyNamedPropertiesNested reference;
|
||||
}
|
||||
|
||||
static class NoCycleButIdenticallyNamedPropertiesNested {
|
||||
|
||||
@Indexed String foo;
|
||||
NoCycleButIndenticallNamedPropertiesDeeplyNested deep;
|
||||
}
|
||||
|
||||
static class NoCycleButIndenticallNamedPropertiesDeeplyNested {
|
||||
|
||||
@Indexed String foo;
|
||||
}
|
||||
}
|
||||
|
||||
private static List<IndexDefinitionHolder> prepareMappingContextAndResolveIndexForType(Class<?> type) {
|
||||
@@ -426,7 +575,15 @@ public class MongoPersistentEntityIndexResolverUnitTests {
|
||||
private static void assertIndexPathAndCollection(String expectedPath, String expectedCollection,
|
||||
IndexDefinitionHolder holder) {
|
||||
|
||||
assertThat(holder.getPath(), equalTo(expectedPath));
|
||||
assertIndexPathAndCollection(new String[] { expectedPath }, expectedCollection, holder);
|
||||
}
|
||||
|
||||
private static void assertIndexPathAndCollection(String[] expectedPaths, String expectedCollection,
|
||||
IndexDefinitionHolder holder) {
|
||||
|
||||
for (String expectedPath : expectedPaths) {
|
||||
assertThat(holder.getIndexDefinition().getIndexKeys().containsField(expectedPath), equalTo(true));
|
||||
}
|
||||
assertThat(holder.getCollection(), equalTo(expectedCollection));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<mongo:mapping-converter id="mappingConverterWithCustomFieldNamingStrategy" field-naming-strategy-ref="customFieldNamingStrategy" />
|
||||
|
||||
<!-- Should work as well as long ass abbreviation is explicitly disabled -->
|
||||
<mongo:mapping-converter id="mappingConverterWithCustomFieldNamingStrategyAndAbbreviationDisabled" field-naming-strategy-ref="customFieldNamingStrategy" abbreviate-field-names="false" />
|
||||
|
||||
<bean id="customFieldNamingStrategy" class="org.mockito.Mockito" factory-method="mock">
|
||||
<property name="type" value="org.springframework.data.mongodb.core.mapping.FieldNamingStrategy" />
|
||||
</bean>
|
||||
</beans>
|
||||
@@ -68,7 +68,7 @@
|
||||
<xi:include href="introduction/introduction.xml"/>
|
||||
<xi:include href="introduction/requirements.xml"/>
|
||||
<xi:include href="introduction/getting-started.xml"/>
|
||||
<xi:include href="https://raw.github.com/spring-projects/spring-data-commons/1.8.0.RC1/src/docbkx/repositories.xml">
|
||||
<xi:include href="https://raw.github.com/spring-projects/spring-data-commons/1.8.0.RELEASE/src/docbkx/repositories.xml">
|
||||
<xi:fallback href="../../../spring-data-commons/src/docbkx/repositories.xml" />
|
||||
</xi:include>
|
||||
</part>
|
||||
@@ -88,10 +88,10 @@
|
||||
<part id="appendix">
|
||||
<title>Appendix</title>
|
||||
|
||||
<xi:include href="https://raw.github.com/spring-projects/spring-data-commons/1.8.0.RC1/src/docbkx/repository-namespace-reference.xml">
|
||||
<xi:include href="https://raw.github.com/spring-projects/spring-data-commons/1.8.0.RELEASE/src/docbkx/repository-namespace-reference.xml">
|
||||
<xi:fallback href="../../../spring-data-commons/src/docbkx/repository-namespace-reference.xml" />
|
||||
</xi:include>
|
||||
<xi:include href="https://raw.github.com/spring-projects/spring-data-commons/1.8.0.RC1/src/docbkx/repository-query-keywords-reference.xml">
|
||||
<xi:include href="https://raw.github.com/spring-projects/spring-data-commons/1.8.0.RELEASE/src/docbkx/repository-query-keywords-reference.xml">
|
||||
<xi:fallback href="../../../spring-data-commons/src/docbkx/repository-query-keywords-reference.xml" />
|
||||
</xi:include>
|
||||
</part>
|
||||
|
||||
@@ -1,6 +1,17 @@
|
||||
Spring Data MongoDB Changelog
|
||||
=============================
|
||||
|
||||
Changes in version 1.5.0.RELEASE (2014-05-20)
|
||||
---------------------------------------------
|
||||
* DATAMONGO-936 - Release 1.5 GA.
|
||||
* DATAMONGO-929 - Index key should be the properties dot path when creating index using @Indexed / @CompoundIndex.
|
||||
* DATAMONGO-928 - Error when using field-naming-strategy-ref.
|
||||
* DATAMONGO-926 - Stack Overflow Error with 1.5.0.RC1 Release.
|
||||
* DATAMONGO-925 - MappingMongoConverterParser is incorrectly rejecting field-naming-strategy-ref XML configuration.
|
||||
* DATAMONGO-647 - Using "OrderBy" in "query by method name" ignores the @Field annotation for field alias.
|
||||
* DATAMONGO-367 - @Indexed field in embedded Object creates new collection.
|
||||
|
||||
|
||||
Changes in version 1.5.0.RC1 (2014-05-02)
|
||||
-----------------------------------------
|
||||
* DATAMONGO-924 - Aggregation not working with as() method in project() pipeline operator.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Spring Data MongoDB 1.5 RC1
|
||||
Spring Data MongoDB 1.5 GA
|
||||
Copyright (c) [2010-2014] Pivotal Software, Inc.
|
||||
|
||||
This product is licensed to you under the Apache License, Version 2.0 (the "License").
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
SPRING DATA MongoDB 1.4.0.RELEASE
|
||||
---------------------------------
|
||||
|
||||
Spring Data MongoDB is released under the terms of the Apache Software License Version 2.0 (see license.txt).
|
||||
|
||||
|
||||
DISTRIBUTION CONTENTS:
|
||||
|
||||
The JARs are available in the 'dist' directory, and the source JARs are in the 'src' directory.
|
||||
|
||||
The reference manual and javadoc are located in the 'docs' directory.
|
||||
|
||||
|
||||
ADDITIONAL RESOURCES:
|
||||
|
||||
Spring Data Homepage: http://projects.spring.io/spring-data
|
||||
Spring Data Forum: http://forum.spring.io/forum/spring-projects/data/nosql
|
||||
Reference in New Issue
Block a user