Compare commits
81 Commits
1.1.0.M2
...
1.1.2.RELE
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
43d9f2f948 | ||
|
|
fbb281959b | ||
|
|
c9ff78d17b | ||
|
|
b6f5614573 | ||
|
|
3c43a43206 | ||
|
|
b2f82bb5bf | ||
|
|
38ccc59137 | ||
|
|
cfa3e467d1 | ||
|
|
138a4942e9 | ||
|
|
a110197b15 | ||
|
|
0745fe1e25 | ||
|
|
e16d6f4529 | ||
|
|
fa1cc5011b | ||
|
|
90d146235c | ||
|
|
23e1ebc000 | ||
|
|
8850c2caf5 | ||
|
|
49d874d984 | ||
|
|
6fc1b7c1f0 | ||
|
|
eb7c0fe1dd | ||
|
|
55dc16d8fa | ||
|
|
4b018a9d7d | ||
|
|
ecf15b93e0 | ||
|
|
6323a86560 | ||
|
|
3b0b7315e1 | ||
|
|
4aeba6f92d | ||
|
|
342f9ae837 | ||
|
|
66d98b355e | ||
|
|
cabbe747f8 | ||
|
|
5ff3064acd | ||
|
|
3001e2941f | ||
|
|
9cf72fbdd4 | ||
|
|
cb5144de0f | ||
|
|
4be90e51ae | ||
|
|
6c368d557b | ||
|
|
a8432e13a1 | ||
|
|
05ac139554 | ||
|
|
3661b2981e | ||
|
|
69bd7acf74 | ||
|
|
d882af257f | ||
|
|
c92058a79a | ||
|
|
ed2b576261 | ||
|
|
6744446a48 | ||
|
|
fdecec48b2 | ||
|
|
f1289c46e6 | ||
|
|
aa0b87be57 | ||
|
|
2040f02d07 | ||
|
|
13a69ecdfd | ||
|
|
f0051deff0 | ||
|
|
05a8148084 | ||
|
|
aaa44b3369 | ||
|
|
7f35c4430d | ||
|
|
114489d19a | ||
|
|
eda8200d51 | ||
|
|
b078ea9ceb | ||
|
|
d90b1a0ddd | ||
|
|
737a42e07a | ||
|
|
22d5d4c019 | ||
|
|
7ac1e7b6e1 | ||
|
|
e86ab783f3 | ||
|
|
6fe3e67ecb | ||
|
|
3b78034c55 | ||
|
|
a06a69797f | ||
|
|
8b1557e38c | ||
|
|
fcdc6d0df2 | ||
|
|
83b6cd7f05 | ||
|
|
38a9a6d51d | ||
|
|
5e2f16c678 | ||
|
|
d7ae95a779 | ||
|
|
8fbdf9afbd | ||
|
|
f5a4d78e62 | ||
|
|
1f4264e6a7 | ||
|
|
05baa851d8 | ||
|
|
35e8ae1224 | ||
|
|
ceec0bcc4a | ||
|
|
0d87e7fa5f | ||
|
|
a530629d97 | ||
|
|
ba0232b187 | ||
|
|
04a17cacb7 | ||
|
|
761d725fce | ||
|
|
726b0b1bcc | ||
|
|
888e031452 |
19
README.md
19
README.md
@@ -1,16 +1,22 @@
|
||||
Spring Data - Document
|
||||
Spring Data MongoDB
|
||||
======================
|
||||
|
||||
The primary goal of the [Spring Data](http://www.springsource.org/spring-data) project is to make it easier to build Spring-powered applications that use new data access technologies such as non-relational databases, map-reduce frameworks, and cloud based data services.
|
||||
As the name implies, the **Document** modules provides integration with document databases such as [MongoDB](http://www.mongodb.org/) and [CouchDB](http://couchdb.apache.org/).
|
||||
|
||||
The Spring Data MongoDB aims to provide a familiar and consistent Spring-based programming model for for new datastores while retaining store-specific features and capabilities. The Spring Data MongoDB project provides integration with the MongoDB document database. Key functional areas of Spring Data MongoDB are a POJO centric model for interacting with a MongoDB DBCollection and easily writing a Repository style data access layer
|
||||
|
||||
Getting Help
|
||||
------------
|
||||
|
||||
At this point your best bet is to look at the Look at the [JavaDocs](http://static.springsource.org/spring-data/data-document/docs/1.0.0.BUILD-SNAPSHOT/spring-data-mongodb/apidocs/) for MongoDB integration and corresponding and source code. For more detailed questions, use the [forum](http://forum.springsource.org/forumdisplay.php?f=80). If you are new to Spring as well as to Spring Data, look for information about [Spring projects](http://www.springsource.org/projects).
|
||||
For a comprehensive treatmet of all the Spring Data MongoDB features, please refer to the The [User Guide](http://static.springsource.org/spring-data/data-mongodb/docs/current/reference/html/)
|
||||
|
||||
The [User Guide](http://static.springsource.org/spring-data/data-document/docs/1.0.0.BUILD-SNAPSHOT/reference/html/) (A work in progress).
|
||||
The [JavaDocs](http://static.springsource.org/spring-data/data-mongodb/docs/current/api/) have extensive comments in them as well.
|
||||
|
||||
The home page of [Spring Data MongoDB](http://www.springsource.org/spring-data/mongodb) contains links to articles and other resources.
|
||||
|
||||
For more detailed questions, use the [forum](http://forum.springsource.org/forumdisplay.php?f=80).
|
||||
|
||||
If you are new to Spring as well as to Spring Data, look for information about [Spring projects](http://www.springsource.org/projects).
|
||||
|
||||
|
||||
Quick Start
|
||||
@@ -137,11 +143,6 @@ This will register an object in the container named PersonRepository. You can u
|
||||
}
|
||||
|
||||
|
||||
## CouchDB
|
||||
|
||||
TBD
|
||||
|
||||
|
||||
Contributing to Spring Data
|
||||
---------------------------
|
||||
|
||||
|
||||
8
pom.xml
8
pom.xml
@@ -4,7 +4,9 @@
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-dist</artifactId>
|
||||
<name>Spring Data MongoDB Distribution</name>
|
||||
<version>1.1.0.M2</version>
|
||||
<description>Spring Data project for MongoDB</description>
|
||||
<url>http://www.springsource.org/spring-data/mongodb</url>
|
||||
<version>1.1.2.RELEASE</version>
|
||||
<packaging>pom</packaging>
|
||||
<modules>
|
||||
<module>spring-data-mongodb</module>
|
||||
@@ -288,4 +290,8 @@
|
||||
</snapshotRepository>
|
||||
</distributionManagement>
|
||||
|
||||
<scm>
|
||||
<url>https://github.com/SpringSource/spring-data-mongodb</url>
|
||||
</scm>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>1.1.0.M2</version>
|
||||
<version>1.1.2.RELEASE</version>
|
||||
<relativePath>../spring-data-mongodb-parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>spring-data-mongodb-cross-store</artifactId>
|
||||
@@ -42,7 +42,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb</artifactId>
|
||||
<version>1.1.0.M2</version>
|
||||
<version>1.1.2.RELEASE</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
log4j.rootCategory=INFO, stdout
|
||||
|
||||
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %40.40c:%4L - %m%n
|
||||
|
||||
log4j.category.org.springframework=INFO
|
||||
log4j.category.org.springframework.data=TRACE
|
||||
|
||||
log4j.category.org.hibernate.SQL=DEBUG
|
||||
# for debugging datasource initialization
|
||||
# log4j.category.test.jdbc=DEBUG
|
||||
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
|
||||
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d %5p %40.40c:%4L - %m%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!--
|
||||
<logger name="org.springframework" level="debug" />
|
||||
-->
|
||||
|
||||
<root level="error">
|
||||
<appender-ref ref="console" />
|
||||
</root>
|
||||
|
||||
</configuration>
|
||||
@@ -4,14 +4,14 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>1.1.0.M2</version>
|
||||
<version>1.1.2.RELEASE</version>
|
||||
<relativePath>../spring-data-mongodb-parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>spring-data-mongodb-log4j</artifactId>
|
||||
<name>Spring Data MongoDB Log4J Appender</name>
|
||||
|
||||
<properties>
|
||||
<mongo.version>2.3</mongo.version>
|
||||
<log4j.version>1.2.16</log4j.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -4,21 +4,95 @@
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<name>Spring Data MongoDB Parent</name>
|
||||
<description>Spring Data project for MongoDB</description>
|
||||
<url>http://www.springsource.org/spring-data/mongodb</url>
|
||||
<version>1.1.0.M2</version>
|
||||
<version>1.1.2.RELEASE</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<id>trisberg</id>
|
||||
<name>Thomas Risberg</name>
|
||||
<email>trisberg at vmware.com</email>
|
||||
<organization>SpringSource</organization>
|
||||
<organizationUrl>http://www.SpringSource.com</organizationUrl>
|
||||
<roles>
|
||||
<role>Project Admin</role>
|
||||
<role>Developer</role>
|
||||
</roles>
|
||||
<timezone>-5</timezone>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>mpollack</id>
|
||||
<name>Mark Pollack</name>
|
||||
<email>mpollack at vmware.com</email>
|
||||
<organization>SpringSource</organization>
|
||||
<organizationUrl>http://www.SpringSource.com</organizationUrl>
|
||||
<roles>
|
||||
<role>Project Admin</role>
|
||||
<role>Developer</role>
|
||||
</roles>
|
||||
<timezone>-5</timezone>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>ogierke</id>
|
||||
<name>Oliver Gierke</name>
|
||||
<email>ogierke at vmware.com</email>
|
||||
<organization>SpringSource</organization>
|
||||
<organizationUrl>http://www.springsource.com</organizationUrl>
|
||||
<roles>
|
||||
<role>Developer</role>
|
||||
</roles>
|
||||
<timezone>+1</timezone>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>jbrisbin</id>
|
||||
<name>Jon Brisbin</name>
|
||||
<email>jbrisbin at vmware.com</email>
|
||||
<organization>SpringSource</organization>
|
||||
<organizationUrl>http://www.springsource.com</organizationUrl>
|
||||
<roles>
|
||||
<role>Developer</role>
|
||||
</roles>
|
||||
<timezone>-6</timezone>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>Apache License, Version 2.0</name>
|
||||
<url>http://www.apache.org/licenses/LICENSE-2.0</url>
|
||||
<comments>
|
||||
Copyright 2010 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.
|
||||
</comments>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<!-- versions for commonly-used dependencies -->
|
||||
<mongo.version>2.9.3</mongo.version>
|
||||
<junit.version>4.10</junit.version>
|
||||
<log4j.version>1.2.16</log4j.version>
|
||||
<logback.version>1.0.6</logback.version>
|
||||
<org.mockito.version>1.9.0</org.mockito.version>
|
||||
<org.slf4j.version>1.6.1</org.slf4j.version>
|
||||
<org.codehaus.jackson.version>1.6.1</org.codehaus.jackson.version>
|
||||
<org.springframework.version.30>3.0.7.RELEASE</org.springframework.version.30>
|
||||
<org.springframework.version.40>4.0.0.RELEASE</org.springframework.version.40>
|
||||
<org.springframework.version.range>[${org.springframework.version.30}, ${org.springframework.version.40})</org.springframework.version.range>
|
||||
<data.commons.version>1.4.0.M1</data.commons.version>
|
||||
<org.springframework.version.range>3.1.2.RELEASE</org.springframework.version.range>
|
||||
<data.commons.version>1.4.1.RELEASE</data.commons.version>
|
||||
<aspectj.version>1.6.11.RELEASE</aspectj.version>
|
||||
<bundlor.failOnWarnings>true</bundlor.failOnWarnings>
|
||||
</properties>
|
||||
@@ -89,14 +163,14 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
<artifactId>jul-to-slf4j</artifactId>
|
||||
<version>${org.slf4j.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>log4j</groupId>
|
||||
<artifactId>log4j</artifactId>
|
||||
<version>${log4j.version}</version>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>${logback.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -161,7 +235,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>2.4</version>
|
||||
<version>2.5.1</version>
|
||||
<configuration>
|
||||
<source>1.5</source>
|
||||
<target>1.5</target>
|
||||
@@ -191,6 +265,9 @@
|
||||
<exclude>**/PerformanceTests.java</exclude>
|
||||
</excludes>
|
||||
<junitArtifactName>junit:junit-dep</junitArtifactName>
|
||||
<systemPropertyVariables>
|
||||
<java.util.logging.config.file>src/test/resources/logging.properties</java.util.logging.config.file>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
@@ -245,6 +322,10 @@
|
||||
<id>spring-plugins-release</id>
|
||||
<url>http://repo.springsource.org/plugins-release</url>
|
||||
</pluginRepository>
|
||||
<pluginRepository>
|
||||
<id>querydsl</id>
|
||||
<url>http://source.mysema.com/maven2/releases</url>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
<repositories>
|
||||
<repository>
|
||||
@@ -269,4 +350,7 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</reporting>
|
||||
<scm>
|
||||
<url>https://github.com/SpringSource/spring-data-mongodb</url>
|
||||
</scm>
|
||||
</project>
|
||||
|
||||
@@ -4,15 +4,14 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>1.1.0.M2</version>
|
||||
<version>1.1.2.RELEASE</version>
|
||||
<relativePath>../spring-data-mongodb-parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>spring-data-mongodb</artifactId>
|
||||
<name>Spring Data MongoDB</name>
|
||||
|
||||
<properties>
|
||||
<mongo.version>2.7.1</mongo.version>
|
||||
<querydsl.version>2.6.0</querydsl.version>
|
||||
<querydsl.version>2.8.2</querydsl.version>
|
||||
<cdi.version>1.0</cdi.version>
|
||||
<validation.version>1.0.0.GA</validation.version>
|
||||
<webbeans.version>1.1.3</webbeans.version>
|
||||
@@ -65,12 +64,6 @@
|
||||
<groupId>org.mongodb</groupId>
|
||||
<artifactId>mongo-java-driver</artifactId>
|
||||
<version>${mongo.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>javax.persistence</groupId>
|
||||
<artifactId>persistence-api</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -78,19 +71,6 @@
|
||||
<artifactId>querydsl-mongodb</artifactId>
|
||||
<version>${querydsl.version}</version>
|
||||
<optional>true</optional>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.google.code.morphia</groupId>
|
||||
<artifactId>morphia</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.mysema.querydsl</groupId>
|
||||
<artifactId>querydsl-apt</artifactId>
|
||||
<version>${querydsl.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -181,7 +161,14 @@
|
||||
<plugin>
|
||||
<groupId>com.mysema.maven</groupId>
|
||||
<artifactId>maven-apt-plugin</artifactId>
|
||||
<version>1.0.2</version>
|
||||
<version>1.0.4</version>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.mysema.querydsl</groupId>
|
||||
<artifactId>querydsl-apt</artifactId>
|
||||
<version>${querydsl.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>generate-test-sources</phase>
|
||||
|
||||
@@ -39,7 +39,7 @@ import org.springframework.util.StringUtils;
|
||||
import com.mongodb.Mongo;
|
||||
|
||||
/**
|
||||
* Base class for Spring Data Mongo configuration using JavaConfig.
|
||||
* Base class for Spring Data MongoDB configuration using JavaConfig.
|
||||
*
|
||||
* @author Mark Pollack
|
||||
* @author Oliver Gierke
|
||||
@@ -96,12 +96,16 @@ public abstract class AbstractMongoConfiguration {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the base package to scan for mapped {@link Document}s.
|
||||
* Return the base package to scan for mapped {@link Document}s. Will return the package name of the configuration
|
||||
* class' (the concrete class, not this one here) by default. So if you have a {@code com.acme.AppConfig} extending
|
||||
* {@link AbstractMongoConfiguration} the base package will be considered {@code com.acme} unless the method is
|
||||
* overriden to implement alternate behaviour.
|
||||
*
|
||||
* @return
|
||||
* @return the base package to scan for mapped {@link Document} classes or {@literal null} to not enable scanning for
|
||||
* entities.
|
||||
*/
|
||||
protected String getMappingBasePackage() {
|
||||
return null;
|
||||
return getClass().getPackage().getName();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -26,4 +26,6 @@ public abstract class BeanNames {
|
||||
static final String MONGO = "mongo";
|
||||
static final String DB_FACTORY = "mongoDbFactory";
|
||||
static final String VALIDATING_EVENT_LISTENER = "validatingMongoEventListener";
|
||||
static final String IS_NEW_STRATEGY_FACTORY = "isNewStrategyFactory";
|
||||
static final String DEFAULT_CONVERTER_BEAN_NAME = "mappingConverter";
|
||||
}
|
||||
|
||||
@@ -24,12 +24,12 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.BeanMetadataElement;
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
@@ -38,6 +38,7 @@ import org.springframework.beans.factory.support.ManagedList;
|
||||
import org.springframework.beans.factory.support.ManagedSet;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
@@ -48,6 +49,7 @@ import org.springframework.core.type.filter.AnnotationTypeFilter;
|
||||
import org.springframework.core.type.filter.AssignableTypeFilter;
|
||||
import org.springframework.core.type.filter.TypeFilter;
|
||||
import org.springframework.data.annotation.Persistent;
|
||||
import org.springframework.data.config.BeanComponentDefinitionBuilder;
|
||||
import org.springframework.data.mongodb.core.convert.CustomConversions;
|
||||
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
|
||||
import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexCreator;
|
||||
@@ -67,25 +69,26 @@ import org.w3c.dom.Element;
|
||||
* @author Oliver Gierke
|
||||
* @author Maciej Walkowiak
|
||||
*/
|
||||
public class MappingMongoConverterParser extends AbstractBeanDefinitionParser {
|
||||
public class MappingMongoConverterParser implements BeanDefinitionParser {
|
||||
|
||||
private static final String BASE_PACKAGE = "base-package";
|
||||
private static final boolean jsr303Present = ClassUtils.isPresent("javax.validation.Validator",
|
||||
MappingMongoConverterParser.class.getClassLoader());
|
||||
|
||||
@Override
|
||||
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext)
|
||||
throws BeanDefinitionStoreException {
|
||||
String id = super.resolveId(element, definition, parserContext);
|
||||
return StringUtils.hasText(id) ? id : "mappingConverter";
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.xml.BeanDefinitionParser#parse(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext)
|
||||
*/
|
||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
|
||||
@Override
|
||||
protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
|
||||
BeanDefinitionRegistry registry = parserContext.getRegistry();
|
||||
|
||||
String id = element.getAttribute(AbstractBeanDefinitionParser.ID_ATTRIBUTE);
|
||||
id = StringUtils.hasText(id) ? id : "mappingConverter";
|
||||
|
||||
parserContext.pushContainingComponent(new CompositeComponentDefinition("Mapping Mongo Converter", element));
|
||||
|
||||
BeanDefinition conversionsDefinition = getCustomConversions(element, parserContext);
|
||||
String ctxRef = potentiallyCreateMappingContext(element, parserContext, conversionsDefinition);
|
||||
String ctxRef = potentiallyCreateMappingContext(element, parserContext, conversionsDefinition, id);
|
||||
|
||||
// Need a reference to a Mongo instance
|
||||
String dbFactoryRef = element.getAttribute("db-factory-ref");
|
||||
@@ -110,18 +113,23 @@ public class MappingMongoConverterParser extends AbstractBeanDefinitionParser {
|
||||
}
|
||||
BeanDefinitionBuilder indexHelperBuilder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(MongoPersistentEntityIndexCreator.class);
|
||||
indexHelperBuilder.addConstructorArgValue(new RuntimeBeanReference(ctxRef));
|
||||
indexHelperBuilder.addConstructorArgValue(new RuntimeBeanReference(dbFactoryRef));
|
||||
registry.registerBeanDefinition(INDEX_HELPER, indexHelperBuilder.getBeanDefinition());
|
||||
indexHelperBuilder.addConstructorArgReference(ctxRef);
|
||||
indexHelperBuilder.addConstructorArgReference(dbFactoryRef);
|
||||
|
||||
parserContext.registerBeanComponent(new BeanComponentDefinition(indexHelperBuilder.getBeanDefinition(),
|
||||
INDEX_HELPER));
|
||||
}
|
||||
|
||||
BeanDefinition validatingMongoEventListener = potentiallyCreateValidatingMongoEventListener(element, parserContext);
|
||||
|
||||
if (validatingMongoEventListener != null) {
|
||||
registry.registerBeanDefinition(VALIDATING_EVENT_LISTENER, validatingMongoEventListener);
|
||||
parserContext.registerBeanComponent(new BeanComponentDefinition(validatingMongoEventListener,
|
||||
VALIDATING_EVENT_LISTENER));
|
||||
}
|
||||
|
||||
return converterBuilder.getBeanDefinition();
|
||||
parserContext.registerBeanComponent(new BeanComponentDefinition(converterBuilder.getBeanDefinition(), id));
|
||||
parserContext.popAndRegisterContainingComponent();
|
||||
return null;
|
||||
}
|
||||
|
||||
private BeanDefinition potentiallyCreateValidatingMongoEventListener(Element element, ParserContext parserContext) {
|
||||
@@ -135,7 +143,6 @@ public class MappingMongoConverterParser extends AbstractBeanDefinitionParser {
|
||||
RuntimeBeanReference validator = getValidator(builder, parserContext);
|
||||
|
||||
if (validator != null) {
|
||||
|
||||
builder.getRawBeanDefinition().setBeanClass(ValidatingMongoEventListener.class);
|
||||
builder.addConstructorArgValue(validator);
|
||||
|
||||
@@ -157,36 +164,42 @@ public class MappingMongoConverterParser extends AbstractBeanDefinitionParser {
|
||||
validatorDef.setSource(source);
|
||||
validatorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
String validatorName = parserContext.getReaderContext().registerWithGeneratedName(validatorDef);
|
||||
parserContext.registerComponent(new BeanComponentDefinition(validatorDef, validatorName));
|
||||
parserContext.registerBeanComponent(new BeanComponentDefinition(validatorDef, validatorName));
|
||||
|
||||
return new RuntimeBeanReference(validatorName);
|
||||
}
|
||||
|
||||
private String potentiallyCreateMappingContext(Element element, ParserContext parserContext,
|
||||
BeanDefinition conversionsDefinition) {
|
||||
static String potentiallyCreateMappingContext(Element element, ParserContext parserContext,
|
||||
BeanDefinition conversionsDefinition, String converterId) {
|
||||
|
||||
String ctxRef = element.getAttribute("mapping-context-ref");
|
||||
if (!StringUtils.hasText(ctxRef)) {
|
||||
BeanDefinitionBuilder mappingContextBuilder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(MongoMappingContext.class);
|
||||
|
||||
Set<String> classesToAdd = getInititalEntityClasses(element, mappingContextBuilder);
|
||||
if (classesToAdd != null) {
|
||||
mappingContextBuilder.addPropertyValue("initialEntitySet", classesToAdd);
|
||||
}
|
||||
|
||||
if (conversionsDefinition != null) {
|
||||
AbstractBeanDefinition simpleTypesDefinition = new GenericBeanDefinition();
|
||||
simpleTypesDefinition.setFactoryBeanName("customConversions");
|
||||
simpleTypesDefinition.setFactoryMethodName("getSimpleTypeHolder");
|
||||
|
||||
mappingContextBuilder.addPropertyValue("simpleTypeHolder", simpleTypesDefinition);
|
||||
}
|
||||
|
||||
parserContext.getRegistry().registerBeanDefinition(MAPPING_CONTEXT, mappingContextBuilder.getBeanDefinition());
|
||||
ctxRef = MAPPING_CONTEXT;
|
||||
if (StringUtils.hasText(ctxRef)) {
|
||||
return ctxRef;
|
||||
}
|
||||
|
||||
BeanComponentDefinitionBuilder componentDefinitionBuilder = new BeanComponentDefinitionBuilder(element,
|
||||
parserContext);
|
||||
|
||||
BeanDefinitionBuilder mappingContextBuilder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(MongoMappingContext.class);
|
||||
|
||||
Set<String> classesToAdd = getInititalEntityClasses(element, mappingContextBuilder);
|
||||
if (classesToAdd != null) {
|
||||
mappingContextBuilder.addPropertyValue("initialEntitySet", classesToAdd);
|
||||
}
|
||||
|
||||
if (conversionsDefinition != null) {
|
||||
AbstractBeanDefinition simpleTypesDefinition = new GenericBeanDefinition();
|
||||
simpleTypesDefinition.setFactoryBeanName("customConversions");
|
||||
simpleTypesDefinition.setFactoryMethodName("getSimpleTypeHolder");
|
||||
|
||||
mappingContextBuilder.addPropertyValue("simpleTypeHolder", simpleTypesDefinition);
|
||||
}
|
||||
|
||||
ctxRef = converterId + "." + MAPPING_CONTEXT;
|
||||
|
||||
parserContext.registerBeanComponent(componentDefinitionBuilder.getComponent(mappingContextBuilder, ctxRef));
|
||||
return ctxRef;
|
||||
}
|
||||
|
||||
@@ -224,7 +237,7 @@ public class MappingMongoConverterParser extends AbstractBeanDefinitionParser {
|
||||
AbstractBeanDefinition conversionsBean = conversionsBuilder.getBeanDefinition();
|
||||
conversionsBean.setSource(parserContext.extractSource(element));
|
||||
|
||||
parserContext.getRegistry().registerBeanDefinition("customConversions", conversionsBean);
|
||||
parserContext.registerBeanComponent(new BeanComponentDefinition(conversionsBean, "customConversions"));
|
||||
|
||||
return conversionsBean;
|
||||
}
|
||||
@@ -232,7 +245,7 @@ public class MappingMongoConverterParser extends AbstractBeanDefinitionParser {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Set<String> getInititalEntityClasses(Element element, BeanDefinitionBuilder builder) {
|
||||
public static Set<String> getInititalEntityClasses(Element element, BeanDefinitionBuilder builder) {
|
||||
|
||||
String basePackage = element.getAttribute(BASE_PACKAGE);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
* Copyright 2011-2012 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.
|
||||
@@ -13,59 +13,53 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.mongodb.core;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.WriteConcern;
|
||||
|
||||
/**
|
||||
* Represents an action taken against the collection. Used by {@link WriteConcernResolver} to determine a custom
|
||||
* WriteConcern based on this information.
|
||||
*
|
||||
* Properties that will always be not-null are collectionName and defaultWriteConcern. The EntityClass is null only for
|
||||
* the MongoActionOperaton.INSERT_LIST.
|
||||
*
|
||||
* {@link WriteConcern} based on this information.
|
||||
* <ul>
|
||||
* <li>INSERT, SAVE have null query</li>
|
||||
* <li>REMOVE has null document</li>
|
||||
* <li>INSERT_LIST has null entityClass, document, and query</li>
|
||||
* <li>INSERT_LIST has null entityType, document, and query</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Mark Pollack
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class MongoAction {
|
||||
|
||||
private String collectionName;
|
||||
|
||||
private WriteConcern defaultWriteConcern;
|
||||
|
||||
private Class<?> entityClass;
|
||||
|
||||
private MongoActionOperation mongoActionOperation;
|
||||
|
||||
private DBObject query;
|
||||
|
||||
private DBObject document;
|
||||
private final String collectionName;
|
||||
private final WriteConcern defaultWriteConcern;
|
||||
private final Class<?> entityType;
|
||||
private final MongoActionOperation mongoActionOperation;
|
||||
private final DBObject query;
|
||||
private final DBObject document;
|
||||
|
||||
/**
|
||||
* Create an instance of a MongoAction
|
||||
* Create an instance of a {@link MongoAction}.
|
||||
*
|
||||
* @param defaultWriteConcern the default write concern
|
||||
* @param defaultWriteConcern the default write concern.
|
||||
* @param mongoActionOperation action being taken against the collection
|
||||
* @param collectionName the collection name
|
||||
* @param entityClass the POJO that is being operated against
|
||||
* @param collectionName the collection name, must not be {@literal null} or empty.
|
||||
* @param entityType the POJO that is being operated against
|
||||
* @param document the converted DBObject from the POJO or Spring Update object
|
||||
* @param query the converted DBOjbect from the Spring Query object
|
||||
*/
|
||||
public MongoAction(WriteConcern defaultWriteConcern, MongoActionOperation mongoActionOperation,
|
||||
String collectionName, Class<?> entityClass, DBObject document, DBObject query) {
|
||||
super();
|
||||
String collectionName, Class<?> entityType, DBObject document, DBObject query) {
|
||||
|
||||
Assert.hasText(collectionName, "Collection name must not be null or empty!");
|
||||
|
||||
this.defaultWriteConcern = defaultWriteConcern;
|
||||
this.mongoActionOperation = mongoActionOperation;
|
||||
this.collectionName = collectionName;
|
||||
this.entityClass = entityClass;
|
||||
this.entityType = entityType;
|
||||
this.query = query;
|
||||
this.document = document;
|
||||
}
|
||||
@@ -78,8 +72,16 @@ public class MongoAction {
|
||||
return defaultWriteConcern;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #getEntityType()} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public Class<?> getEntityClass() {
|
||||
return entityClass;
|
||||
return entityType;
|
||||
}
|
||||
|
||||
public Class<?> getEntityType() {
|
||||
return entityType;
|
||||
}
|
||||
|
||||
public MongoActionOperation getMongoActionOperation() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
* Copyright 2011-2012 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.
|
||||
@@ -20,8 +20,8 @@ package org.springframework.data.mongodb.core;
|
||||
* for a given mutating operation
|
||||
*
|
||||
* @author Mark Pollack
|
||||
* @author Oliver Gierke
|
||||
* @see MongoAction
|
||||
*
|
||||
*/
|
||||
public enum MongoActionOperation {
|
||||
|
||||
|
||||
@@ -79,21 +79,18 @@ public abstract class MongoDbUtils {
|
||||
|
||||
DbHolder dbHolder = (DbHolder) TransactionSynchronizationManager.getResource(mongo);
|
||||
|
||||
if (dbHolder != null && !dbHolder.isEmpty()) {
|
||||
// Do we have a populated holder and TX sync active?
|
||||
if (dbHolder != null && !dbHolder.isEmpty() && TransactionSynchronizationManager.isSynchronizationActive()) {
|
||||
|
||||
DB db = null;
|
||||
DB db = dbHolder.getDB(databaseName);
|
||||
|
||||
if (TransactionSynchronizationManager.isSynchronizationActive() && dbHolder.doesNotHoldNonDefaultDB()) {
|
||||
// DB found but not yet synchronized
|
||||
if (db != null && !dbHolder.isSynchronizedWithTransaction()) {
|
||||
|
||||
db = dbHolder.getDB(databaseName);
|
||||
LOGGER.debug("Registering Spring transaction synchronization for existing MongoDB {}.", databaseName);
|
||||
|
||||
if (db != null && !dbHolder.isSynchronizedWithTransaction()) {
|
||||
|
||||
LOGGER.debug("Registering Spring transaction synchronization for existing MongoDB {}.", databaseName);
|
||||
|
||||
TransactionSynchronizationManager.registerSynchronization(new MongoSynchronization(dbHolder, mongo));
|
||||
dbHolder.setSynchronizedWithTransaction(true);
|
||||
}
|
||||
TransactionSynchronizationManager.registerSynchronization(new MongoSynchronization(dbHolder, mongo));
|
||||
dbHolder.setSynchronizedWithTransaction(true);
|
||||
}
|
||||
|
||||
if (db != null) {
|
||||
@@ -101,24 +98,27 @@ public abstract class MongoDbUtils {
|
||||
}
|
||||
}
|
||||
|
||||
// Lookup fresh database instance
|
||||
LOGGER.debug("Getting Mongo Database name=[{}]", databaseName);
|
||||
|
||||
DB db = mongo.getDB(databaseName);
|
||||
boolean credentialsGiven = credentials.hasUsername() && credentials.hasPassword();
|
||||
|
||||
if (credentialsGiven && !db.isAuthenticated()) {
|
||||
synchronized (db) {
|
||||
|
||||
String username = credentials.getUsername();
|
||||
String password = credentials.hasPassword() ? credentials.getPassword() : null;
|
||||
if (credentialsGiven && !db.isAuthenticated()) {
|
||||
|
||||
if (!db.authenticate(username, password == null ? null : password.toCharArray())) {
|
||||
throw new CannotGetMongoDbConnectionException("Failed to authenticate to database [" + databaseName
|
||||
+ "], username = [" + username + "], password = [" + password + "]", databaseName, credentials);
|
||||
String username = credentials.getUsername();
|
||||
String password = credentials.hasPassword() ? credentials.getPassword() : null;
|
||||
|
||||
if (!db.authenticate(username, password == null ? null : password.toCharArray())) {
|
||||
throw new CannotGetMongoDbConnectionException("Failed to authenticate to database [" + databaseName
|
||||
+ "], username = [" + username + "], password = [ -not-shown- ]", databaseName, credentials);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Use same Session for further Mongo actions within the transaction.
|
||||
// Thread object will get removed by synchronization at transaction completion.
|
||||
// TX sync active, bind new database to thread
|
||||
if (TransactionSynchronizationManager.isSynchronizationActive()) {
|
||||
|
||||
LOGGER.debug("Registering Spring transaction synchronization for MongoDB instance {}.", databaseName);
|
||||
@@ -162,7 +162,7 @@ public abstract class MongoDbUtils {
|
||||
return false;
|
||||
}
|
||||
DbHolder dbHolder = (DbHolder) TransactionSynchronizationManager.getResource(mongo);
|
||||
return (dbHolder != null && dbHolder.containsDB(db));
|
||||
return dbHolder != null && dbHolder.containsDB(db);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2011 the original author or authors.
|
||||
* Copyright 2010-2013 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.
|
||||
@@ -15,12 +15,6 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core;
|
||||
|
||||
import com.mongodb.MongoException;
|
||||
import com.mongodb.MongoException.CursorNotFound;
|
||||
import com.mongodb.MongoException.DuplicateKey;
|
||||
import com.mongodb.MongoException.Network;
|
||||
import com.mongodb.MongoInternalException;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
@@ -29,21 +23,26 @@ import org.springframework.dao.InvalidDataAccessResourceUsageException;
|
||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||
import org.springframework.data.mongodb.UncategorizedMongoDbException;
|
||||
|
||||
import com.mongodb.MongoException;
|
||||
import com.mongodb.MongoException.CursorNotFound;
|
||||
import com.mongodb.MongoException.DuplicateKey;
|
||||
import com.mongodb.MongoException.Network;
|
||||
import com.mongodb.MongoInternalException;
|
||||
|
||||
/**
|
||||
* Simple {@link PersistenceExceptionTranslator} for Mongo. Convert the given runtime exception to an appropriate
|
||||
* exception from the {@code org.springframework.dao} hierarchy. Return {@literal null} if no translation is
|
||||
* appropriate: any other exception may have resulted from user code, and should not be translated.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Michal Vich
|
||||
*/
|
||||
public class MongoExceptionTranslator implements PersistenceExceptionTranslator {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.dao.support.PersistenceExceptionTranslator#
|
||||
* translateExceptionIfPossible(java.lang.RuntimeException)
|
||||
*/
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.dao.support.PersistenceExceptionTranslator#translateExceptionIfPossible(java.lang.RuntimeException)
|
||||
*/
|
||||
public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
|
||||
|
||||
// Check for well-known MongoException subclasses.
|
||||
@@ -52,14 +51,23 @@ public class MongoExceptionTranslator implements PersistenceExceptionTranslator
|
||||
if (ex instanceof DuplicateKey) {
|
||||
return new DuplicateKeyException(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
if (ex instanceof Network) {
|
||||
return new DataAccessResourceFailureException(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
if (ex instanceof CursorNotFound) {
|
||||
return new DataAccessResourceFailureException(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
if (ex instanceof MongoInternalException) {
|
||||
return new InvalidDataAccessResourceUsageException(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
if (ex instanceof MongoException) {
|
||||
|
||||
int code = ((MongoException) ex).getCode();
|
||||
|
||||
if (code == 11000 || code == 11001) {
|
||||
throw new DuplicateKeyException(ex.getMessage(), ex);
|
||||
} else if (code == 12000 || code == 13440) {
|
||||
@@ -69,9 +77,6 @@ public class MongoExceptionTranslator implements PersistenceExceptionTranslator
|
||||
}
|
||||
return new UncategorizedMongoDbException(ex.getMessage(), ex);
|
||||
}
|
||||
if (ex instanceof MongoInternalException) {
|
||||
return new InvalidDataAccessResourceUsageException(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
// If we get here, we have an exception that resulted from user code,
|
||||
// rather than the persistence provider, so we return null to indicate
|
||||
|
||||
@@ -16,13 +16,14 @@
|
||||
package org.springframework.data.mongodb.core;
|
||||
|
||||
import static org.springframework.data.mongodb.core.query.Criteria.*;
|
||||
import static org.springframework.data.mongodb.core.query.SerializationUtils.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -37,6 +38,7 @@ import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.context.ApplicationEventPublisherAware;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.io.Resource;
|
||||
@@ -44,6 +46,7 @@ import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.dao.OptimisticLockingFailureException;
|
||||
import org.springframework.data.authentication.UserCredentials;
|
||||
import org.springframework.data.convert.EntityReader;
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
@@ -98,6 +101,7 @@ import com.mongodb.ReadPreference;
|
||||
import com.mongodb.WriteConcern;
|
||||
import com.mongodb.WriteResult;
|
||||
import com.mongodb.util.JSON;
|
||||
import com.mongodb.util.JSONParseException;
|
||||
|
||||
/**
|
||||
* Primary implementation of {@link MongoOperations}.
|
||||
@@ -107,40 +111,24 @@ import com.mongodb.util.JSON;
|
||||
* @author Mark Pollack
|
||||
* @author Oliver Gierke
|
||||
* @author Amol Nayak
|
||||
* @author Patryk Wasik
|
||||
*/
|
||||
public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(MongoTemplate.class);
|
||||
private static final String ID = "_id";
|
||||
private static final String ID_FIELD = "_id";
|
||||
private static final WriteResultChecking DEFAULT_WRITE_RESULT_CHECKING = WriteResultChecking.NONE;
|
||||
@SuppressWarnings("serial")
|
||||
private static final List<String> ITERABLE_CLASSES = new ArrayList<String>() {
|
||||
{
|
||||
add(List.class.getName());
|
||||
add(Collection.class.getName());
|
||||
add(Iterator.class.getName());
|
||||
}
|
||||
};
|
||||
private static final Collection<String> ITERABLE_CLASSES;
|
||||
|
||||
/*
|
||||
* WriteConcern to be used for write operations if it has been specified.
|
||||
* Otherwise we should not use a WriteConcern defaulting to the one set for
|
||||
* the DB or Collection.
|
||||
*/
|
||||
private WriteConcern writeConcern = null;
|
||||
static {
|
||||
|
||||
private WriteConcernResolver writeConcernResolver = new DefaultWriteConcernResolver();
|
||||
Set<String> iterableClasses = new HashSet<String>();
|
||||
iterableClasses.add(List.class.getName());
|
||||
iterableClasses.add(Collection.class.getName());
|
||||
iterableClasses.add(Iterator.class.getName());
|
||||
|
||||
/*
|
||||
* WriteResultChecking to be used for write operations if it has been
|
||||
* specified. Otherwise we should not do any checking.
|
||||
*/
|
||||
private WriteResultChecking writeResultChecking = WriteResultChecking.NONE;
|
||||
|
||||
/**
|
||||
* Set the ReadPreference when operating on a collection. See {@link #prepareCollection(DBCollection)}
|
||||
*/
|
||||
private ReadPreference readPreference = null;
|
||||
ITERABLE_CLASSES = Collections.unmodifiableCollection(iterableClasses);
|
||||
}
|
||||
|
||||
private final MongoConverter mongoConverter;
|
||||
private final MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
|
||||
@@ -148,6 +136,10 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
private final MongoExceptionTranslator exceptionTranslator = new MongoExceptionTranslator();
|
||||
private final QueryMapper mapper;
|
||||
|
||||
private WriteConcern writeConcern;
|
||||
private WriteConcernResolver writeConcernResolver = DefaultWriteConcernResolver.INSTANCE;
|
||||
private WriteResultChecking writeResultChecking = WriteResultChecking.NONE;
|
||||
private ReadPreference readPreference;
|
||||
private ApplicationEventPublisher eventPublisher;
|
||||
private ResourceLoader resourceLoader;
|
||||
private MongoPersistentEntityIndexCreator indexCreator;
|
||||
@@ -155,8 +147,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
/**
|
||||
* Constructor used for a basic template configuration
|
||||
*
|
||||
* @param mongo
|
||||
* @param databaseName
|
||||
* @param mongo must not be {@literal null}.
|
||||
* @param databaseName must not be {@literal null} or empty.
|
||||
*/
|
||||
public MongoTemplate(Mongo mongo, String databaseName) {
|
||||
this(new SimpleMongoDbFactory(mongo, databaseName), null);
|
||||
@@ -166,8 +158,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
* Constructor used for a template configuration with user credentials in the form of
|
||||
* {@link org.springframework.data.authentication.UserCredentials}
|
||||
*
|
||||
* @param mongo
|
||||
* @param databaseName
|
||||
* @param mongo must not be {@literal null}.
|
||||
* @param databaseName must not be {@literal null} or empty.
|
||||
* @param userCredentials
|
||||
*/
|
||||
public MongoTemplate(Mongo mongo, String databaseName, UserCredentials userCredentials) {
|
||||
@@ -175,9 +167,9 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor used for a basic template configuration
|
||||
* Constructor used for a basic template configuration.
|
||||
*
|
||||
* @param mongoDbFactory
|
||||
* @param mongoDbFactory must not be {@literal null}.
|
||||
*/
|
||||
public MongoTemplate(MongoDbFactory mongoDbFactory) {
|
||||
this(mongoDbFactory, null);
|
||||
@@ -186,7 +178,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
/**
|
||||
* Constructor used for a basic template configuration.
|
||||
*
|
||||
* @param mongoDbFactory
|
||||
* @param mongoDbFactory must not be {@literal null}.
|
||||
* @param mongoConverter
|
||||
*/
|
||||
public MongoTemplate(MongoDbFactory mongoDbFactory, MongoConverter mongoConverter) {
|
||||
@@ -207,7 +199,6 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
((ApplicationEventPublisherAware) mappingContext).setApplicationEventPublisher(eventPublisher);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -221,7 +212,9 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the {@link WriteConcern} to be used with the template.
|
||||
* Configures the {@link WriteConcern} to be used with the template. If none is configured the {@link WriteConcern}
|
||||
* configured on the {@link MongoDbFactory} will apply. If you configured a {@link Mongo} instance no
|
||||
* {@link WriteConcern} will be used.
|
||||
*
|
||||
* @param writeConcern
|
||||
*/
|
||||
@@ -248,11 +241,14 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
this.readPreference = readPreference;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
|
||||
*/
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
String[] beans = applicationContext.getBeanNamesForType(MongoPersistentEntityIndexCreator.class);
|
||||
if ((null == beans || beans.length == 0) && applicationContext instanceof ConfigurableApplicationContext) {
|
||||
((ConfigurableApplicationContext) applicationContext).addApplicationListener(indexCreator);
|
||||
}
|
||||
|
||||
prepareIndexCreator(applicationContext);
|
||||
|
||||
eventPublisher = applicationContext;
|
||||
if (mappingContext instanceof ApplicationEventPublisherAware) {
|
||||
((ApplicationEventPublisherAware) mappingContext).setApplicationEventPublisher(eventPublisher);
|
||||
@@ -260,6 +256,30 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
resourceLoader = applicationContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inspects the given {@link ApplicationContext} for {@link MongoPersistentEntityIndexCreator} and those in turn if
|
||||
* they were registered for the current {@link MappingContext}. If no creator for the current {@link MappingContext}
|
||||
* can be found we manually add the internally created one as {@link ApplicationListener} to make sure indexes get
|
||||
* created appropriately for entity types persisted through this {@link MongoTemplate} instance.
|
||||
*
|
||||
* @param context must not be {@literal null}.
|
||||
*/
|
||||
private void prepareIndexCreator(ApplicationContext context) {
|
||||
|
||||
String[] indexCreators = context.getBeanNamesForType(MongoPersistentEntityIndexCreator.class);
|
||||
|
||||
for (String creator : indexCreators) {
|
||||
MongoPersistentEntityIndexCreator creatorBean = context.getBean(creator, MongoPersistentEntityIndexCreator.class);
|
||||
if (creatorBean.isIndexCreatorFor(mappingContext)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (context instanceof ConfigurableApplicationContext) {
|
||||
((ConfigurableApplicationContext) context).addApplicationListener(indexCreator);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default {@link org.springframework.data.mongodb.core.core.convert.MongoConverter}.
|
||||
*
|
||||
@@ -337,7 +357,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug(String.format("Executing query: %s sort: %s fields: %s in collection: $s",
|
||||
SerializationUtils.serializeToJsonSafely(queryObject), sortObject, fieldsObject, collectionName));
|
||||
serializeToJsonSafely(queryObject), sortObject, fieldsObject, collectionName));
|
||||
}
|
||||
|
||||
this.executeQueryInternal(new FindCallback(queryObject, fieldsObject), preparer, dch, collectionName);
|
||||
@@ -456,7 +476,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
} else {
|
||||
query.limit(1);
|
||||
List<T> results = find(query, entityClass, collectionName);
|
||||
return (results.isEmpty() ? null : results.get(0));
|
||||
return results.isEmpty() ? null : results.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -467,19 +487,23 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
|
||||
public <T> List<T> find(final Query query, Class<T> entityClass, String collectionName) {
|
||||
CursorPreparer cursorPreparer = query == null ? null : new QueryCursorPreparer(query);
|
||||
return doFind(collectionName, query.getQueryObject(), query.getFieldsObject(), entityClass, cursorPreparer);
|
||||
|
||||
if (query == null) {
|
||||
return findAll(entityClass, collectionName);
|
||||
}
|
||||
|
||||
return doFind(collectionName, query.getQueryObject(), query.getFieldsObject(), entityClass,
|
||||
new QueryCursorPreparer(query));
|
||||
}
|
||||
|
||||
public <T> T findById(Object id, Class<T> entityClass) {
|
||||
MongoPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(entityClass);
|
||||
return findById(id, entityClass, persistentEntity.getCollection());
|
||||
return findById(id, entityClass, determineCollectionName(entityClass));
|
||||
}
|
||||
|
||||
public <T> T findById(Object id, Class<T> entityClass, String collectionName) {
|
||||
MongoPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(entityClass);
|
||||
MongoPersistentProperty idProperty = persistentEntity.getIdProperty();
|
||||
String idKey = idProperty == null ? ID : idProperty.getName();
|
||||
MongoPersistentProperty idProperty = persistentEntity == null ? null : persistentEntity.getIdProperty();
|
||||
String idKey = idProperty == null ? ID_FIELD : idProperty.getName();
|
||||
return doFindOne(collectionName, new BasicDBObject(idKey, id), null, entityClass);
|
||||
}
|
||||
|
||||
@@ -624,6 +648,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
assertUpdateableIdIfNotSet(objectToSave);
|
||||
|
||||
initializeVersionProperty(objectToSave);
|
||||
|
||||
BasicDBObject dbDoc = new BasicDBObject();
|
||||
|
||||
maybeEmitEvent(new BeforeConvertEvent<T>(objectToSave));
|
||||
@@ -636,6 +662,16 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
maybeEmitEvent(new AfterSaveEvent<T>(objectToSave, dbDoc));
|
||||
}
|
||||
|
||||
private void initializeVersionProperty(Object entity) {
|
||||
|
||||
MongoPersistentEntity<?> mongoPersistentEntity = getPersistentEntity(entity.getClass());
|
||||
|
||||
if (mongoPersistentEntity == null || mongoPersistentEntity.hasVersionProperty()) {
|
||||
BeanWrapper<PersistentEntity<Object, ?>, Object> wrapper = BeanWrapper.create(entity, null);
|
||||
wrapper.setProperty(mongoPersistentEntity.getVersionProperty(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
public void insert(Collection<? extends Object> batchToSave, Class<?> entityClass) {
|
||||
doInsertBatch(determineCollectionName(entityClass), batchToSave, this.mongoConverter);
|
||||
}
|
||||
@@ -680,6 +716,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
List<DBObject> dbObjectList = new ArrayList<DBObject>();
|
||||
for (T o : batchToSave) {
|
||||
|
||||
initializeVersionProperty(o);
|
||||
BasicDBObject dbDoc = new BasicDBObject();
|
||||
|
||||
maybeEmitEvent(new BeforeConvertEvent<T>(o));
|
||||
@@ -700,21 +738,83 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
|
||||
public void save(Object objectToSave) {
|
||||
|
||||
Assert.notNull(objectToSave);
|
||||
save(objectToSave, determineEntityCollectionName(objectToSave));
|
||||
}
|
||||
|
||||
public void save(Object objectToSave, String collectionName) {
|
||||
doSave(collectionName, objectToSave, this.mongoConverter);
|
||||
|
||||
Assert.notNull(objectToSave);
|
||||
Assert.hasText(collectionName);
|
||||
|
||||
MongoPersistentEntity<?> mongoPersistentEntity = getPersistentEntity(objectToSave.getClass());
|
||||
|
||||
// No optimistic locking -> simple save
|
||||
if (mongoPersistentEntity == null || !mongoPersistentEntity.hasVersionProperty()) {
|
||||
doSave(collectionName, objectToSave, this.mongoConverter);
|
||||
return;
|
||||
}
|
||||
|
||||
doSaveVersioned(objectToSave, mongoPersistentEntity, collectionName);
|
||||
}
|
||||
|
||||
private <T> void doSaveVersioned(T objectToSave, MongoPersistentEntity<?> entity, String collectionName) {
|
||||
|
||||
BeanWrapper<PersistentEntity<T, ?>, T> beanWrapper = BeanWrapper.create(objectToSave,
|
||||
this.mongoConverter.getConversionService());
|
||||
MongoPersistentProperty idProperty = entity.getIdProperty();
|
||||
MongoPersistentProperty versionProperty = entity.getVersionProperty();
|
||||
|
||||
Number version = beanWrapper.getProperty(versionProperty, Number.class, !versionProperty.usePropertyAccess());
|
||||
|
||||
// Fresh instance -> initialize version property
|
||||
if (version == null) {
|
||||
beanWrapper.setProperty(versionProperty, 0);
|
||||
doSave(collectionName, objectToSave, this.mongoConverter);
|
||||
} else {
|
||||
|
||||
assertUpdateableIdIfNotSet(objectToSave);
|
||||
|
||||
// Create query for entity with the id and old version
|
||||
Object id = beanWrapper.getProperty(idProperty);
|
||||
Query query = new Query(Criteria.where(idProperty.getName()).is(id).and(versionProperty.getName()).is(version));
|
||||
|
||||
// Bump version number
|
||||
Number number = beanWrapper.getProperty(versionProperty, Number.class, false);
|
||||
beanWrapper.setProperty(versionProperty, number.longValue() + 1);
|
||||
|
||||
BasicDBObject dbObject = new BasicDBObject();
|
||||
|
||||
maybeEmitEvent(new BeforeConvertEvent<T>(objectToSave));
|
||||
this.mongoConverter.write(objectToSave, dbObject);
|
||||
|
||||
maybeEmitEvent(new BeforeSaveEvent<T>(objectToSave, dbObject));
|
||||
Update update = Update.fromDBObject(dbObject, ID_FIELD);
|
||||
|
||||
updateFirst(query, update, objectToSave.getClass());
|
||||
maybeEmitEvent(new AfterSaveEvent<T>(objectToSave, dbObject));
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T> void doSave(String collectionName, T objectToSave, MongoWriter<T> writer) {
|
||||
|
||||
assertUpdateableIdIfNotSet(objectToSave);
|
||||
|
||||
BasicDBObject dbDoc = new BasicDBObject();
|
||||
DBObject dbDoc = new BasicDBObject();
|
||||
|
||||
maybeEmitEvent(new BeforeConvertEvent<T>(objectToSave));
|
||||
writer.write(objectToSave, dbDoc);
|
||||
|
||||
if (!(objectToSave instanceof String)) {
|
||||
writer.write(objectToSave, dbDoc);
|
||||
} else {
|
||||
try {
|
||||
objectToSave = (T) JSON.parse((String) objectToSave);
|
||||
} catch (JSONParseException e) {
|
||||
throw new MappingException("Could not parse given String to save into a JSON document!", e);
|
||||
}
|
||||
}
|
||||
|
||||
maybeEmitEvent(new BeforeSaveEvent<T>(objectToSave, dbDoc));
|
||||
Object id = saveDBObject(collectionName, dbDoc, objectToSave.getClass());
|
||||
@@ -725,21 +825,17 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
protected Object insertDBObject(final String collectionName, final DBObject dbDoc, final Class<?> entityClass) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("insert DBObject containing fields: " + dbDoc.keySet() + " in collection: " + collectionName);
|
||||
LOGGER.debug("Inserting DBObject containing fields: " + dbDoc.keySet() + " in collection: " + collectionName);
|
||||
}
|
||||
return execute(collectionName, new CollectionCallback<Object>() {
|
||||
public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||
MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.INSERT, collectionName,
|
||||
entityClass, dbDoc, null);
|
||||
WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction);
|
||||
WriteResult wr;
|
||||
if (writeConcernToUse == null) {
|
||||
wr = collection.insert(dbDoc);
|
||||
} else {
|
||||
wr = collection.insert(dbDoc, writeConcernToUse);
|
||||
}
|
||||
handleAnyWriteResultErrors(wr, dbDoc, "insert");
|
||||
return dbDoc.get(ID);
|
||||
WriteResult writeResult = writeConcernToUse == null ? collection.insert(dbDoc) : collection.insert(dbDoc,
|
||||
writeConcernToUse);
|
||||
handleAnyWriteResultErrors(writeResult, dbDoc, MongoActionOperation.INSERT);
|
||||
return dbDoc.get(ID_FIELD);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -750,27 +846,23 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("insert list of DBObjects containing " + dbDocList.size() + " items");
|
||||
LOGGER.debug("Inserting list of DBObjects containing " + dbDocList.size() + " items");
|
||||
}
|
||||
execute(collectionName, new CollectionCallback<Void>() {
|
||||
public Void doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||
MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.INSERT_LIST, collectionName, null,
|
||||
null, null);
|
||||
WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction);
|
||||
WriteResult wr;
|
||||
if (writeConcernToUse == null) {
|
||||
wr = collection.insert(dbDocList);
|
||||
} else {
|
||||
wr = collection.insert(dbDocList.toArray((DBObject[]) new BasicDBObject[dbDocList.size()]), writeConcernToUse);
|
||||
}
|
||||
handleAnyWriteResultErrors(wr, null, "insert_list");
|
||||
WriteResult writeResult = writeConcernToUse == null ? collection.insert(dbDocList) : collection.insert(
|
||||
dbDocList.toArray((DBObject[]) new BasicDBObject[dbDocList.size()]), writeConcernToUse);
|
||||
handleAnyWriteResultErrors(writeResult, null, MongoActionOperation.INSERT_LIST);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
List<ObjectId> ids = new ArrayList<ObjectId>();
|
||||
for (DBObject dbo : dbDocList) {
|
||||
Object id = dbo.get(ID);
|
||||
Object id = dbo.get(ID_FIELD);
|
||||
if (id instanceof ObjectId) {
|
||||
ids.add((ObjectId) id);
|
||||
} else {
|
||||
@@ -783,21 +875,17 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
protected Object saveDBObject(final String collectionName, final DBObject dbDoc, final Class<?> entityClass) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("save DBObject containing fields: " + dbDoc.keySet());
|
||||
LOGGER.debug("Saving DBObject containing fields: " + dbDoc.keySet());
|
||||
}
|
||||
return execute(collectionName, new CollectionCallback<Object>() {
|
||||
public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||
MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.SAVE, collectionName, entityClass,
|
||||
dbDoc, null);
|
||||
WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction);
|
||||
WriteResult wr;
|
||||
if (writeConcernToUse == null) {
|
||||
wr = collection.save(dbDoc);
|
||||
} else {
|
||||
wr = collection.save(dbDoc, writeConcernToUse);
|
||||
}
|
||||
handleAnyWriteResultErrors(wr, dbDoc, "save");
|
||||
return dbDoc.get(ID);
|
||||
WriteResult writeResult = writeConcernToUse == null ? collection.save(dbDoc) : collection.save(dbDoc,
|
||||
writeConcernToUse);
|
||||
handleAnyWriteResultErrors(writeResult, dbDoc, MongoActionOperation.SAVE);
|
||||
return dbDoc.get(ID_FIELD);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -840,21 +928,25 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
entity);
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("calling update using query: " + queryObj + " and update: " + updateObj + " in collection: "
|
||||
LOGGER.debug("Calling update using query: " + queryObj + " and update: " + updateObj + " in collection: "
|
||||
+ collectionName);
|
||||
}
|
||||
|
||||
WriteResult wr;
|
||||
MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.UPDATE, collectionName,
|
||||
entityClass, updateObj, queryObj);
|
||||
WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction);
|
||||
if (writeConcernToUse == null) {
|
||||
wr = collection.update(queryObj, updateObj, upsert, multi);
|
||||
} else {
|
||||
wr = collection.update(queryObj, updateObj, upsert, multi, writeConcernToUse);
|
||||
WriteResult writeResult = writeConcernToUse == null ? collection.update(queryObj, updateObj, upsert, multi)
|
||||
: collection.update(queryObj, updateObj, upsert, multi, writeConcernToUse);
|
||||
|
||||
if (entity != null && entity.hasVersionProperty() && !multi) {
|
||||
if (writeResult.getN() == 0) {
|
||||
throw new OptimisticLockingFailureException("Optimistic lock exception on saving entity: "
|
||||
+ updateObj.toMap().toString());
|
||||
}
|
||||
}
|
||||
handleAnyWriteResultErrors(wr, queryObj, "update with '" + updateObj + "'");
|
||||
return wr;
|
||||
|
||||
handleAnyWriteResultErrors(writeResult, queryObj, MongoActionOperation.UPDATE);
|
||||
return writeResult;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -876,12 +968,12 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
return;
|
||||
}
|
||||
|
||||
remove(getIdQueryFor(object), collection);
|
||||
doRemove(collection, getIdQueryFor(object), object.getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Query} for the given entity by its id.
|
||||
*
|
||||
*
|
||||
* @param object must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
@@ -890,7 +982,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
Assert.notNull(object);
|
||||
|
||||
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(object.getClass());
|
||||
MongoPersistentProperty idProp = entity.getIdProperty();
|
||||
MongoPersistentProperty idProp = entity == null ? null : entity.getIdProperty();
|
||||
|
||||
if (idProp == null) {
|
||||
throw new MappingException("No id property found for object of type " + entity.getType().getName());
|
||||
@@ -906,7 +998,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
private void assertUpdateableIdIfNotSet(Object entity) {
|
||||
|
||||
MongoPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(entity.getClass());
|
||||
MongoPersistentProperty idProperty = persistentEntity.getIdProperty();
|
||||
MongoPersistentProperty idProperty = persistentEntity == null ? null : persistentEntity.getIdProperty();
|
||||
|
||||
if (idProperty == null) {
|
||||
return;
|
||||
@@ -928,27 +1020,30 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
|
||||
protected <T> void doRemove(final String collectionName, final Query query, final Class<T> entityClass) {
|
||||
|
||||
if (query == null) {
|
||||
throw new InvalidDataAccessApiUsageException("Query passed in to remove can't be null");
|
||||
}
|
||||
|
||||
final DBObject queryObject = query.getQueryObject();
|
||||
final MongoPersistentEntity<?> entity = getPersistentEntity(entityClass);
|
||||
|
||||
execute(collectionName, new CollectionCallback<Void>() {
|
||||
public Void doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||
|
||||
DBObject dboq = mapper.getMappedObject(queryObject, entity);
|
||||
WriteResult wr = null;
|
||||
|
||||
MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.REMOVE, collectionName,
|
||||
entityClass, null, queryObject);
|
||||
WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction);
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("remove using query: " + dboq + " in collection: " + collection.getName());
|
||||
LOGGER.debug("Remove using query: {} in collection: {}.", new Object[] { dboq, collection.getName() });
|
||||
}
|
||||
if (writeConcernToUse == null) {
|
||||
wr = collection.remove(dboq);
|
||||
} else {
|
||||
wr = collection.remove(dboq, writeConcernToUse);
|
||||
}
|
||||
handleAnyWriteResultErrors(wr, dboq, "remove");
|
||||
|
||||
WriteResult wr = writeConcernToUse == null ? collection.remove(dboq) : collection.remove(dboq,
|
||||
writeConcernToUse);
|
||||
handleAnyWriteResultErrors(wr, dboq, MongoActionOperation.REMOVE);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
@@ -1005,8 +1100,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
handleCommandError(commandResult, commandObject);
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug(String.format("MapReduce command result = [%s]",
|
||||
SerializationUtils.serializeToJsonSafely(commandObject)));
|
||||
LOGGER.debug("MapReduce command result = [{}]", serializeToJsonSafely(commandObject));
|
||||
}
|
||||
|
||||
MapReduceOutput mapReduceOutput = new MapReduceOutput(inputCollection, commandObject, commandResult);
|
||||
@@ -1059,15 +1153,14 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
DBObject commandObject = new BasicDBObject("group", dbo);
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug(String.format("Executing Group with DBObject [%s]",
|
||||
SerializationUtils.serializeToJsonSafely(commandObject)));
|
||||
LOGGER.debug("Executing Group with DBObject [{}]", serializeToJsonSafely(commandObject));
|
||||
}
|
||||
|
||||
CommandResult commandResult = executeCommand(commandObject, getDb().getOptions());
|
||||
handleCommandError(commandResult, commandObject);
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Group command result = [" + commandResult + "]");
|
||||
LOGGER.debug("Group command result = [{}]", commandResult);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -1172,7 +1265,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
/**
|
||||
* Create the specified collection using the provided options
|
||||
*
|
||||
*
|
||||
* @param collectionName
|
||||
* @param collectionOptions
|
||||
* @return the collection that was created
|
||||
@@ -1183,7 +1276,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
DBCollection coll = db.createCollection(collectionName, collectionOptions);
|
||||
// TODO: Emit a collection created event
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Created collection [" + coll.getFullName() + "]");
|
||||
LOGGER.debug("Created collection [{}]", coll.getFullName());
|
||||
}
|
||||
return coll;
|
||||
}
|
||||
@@ -1194,7 +1287,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
* Map the results of an ad-hoc query on the default MongoDB collection to an object using the template's converter
|
||||
* <p/>
|
||||
* The query document is specified as a standard DBObject and so is the fields specification.
|
||||
*
|
||||
*
|
||||
* @param collectionName name of the collection to retrieve the objects from
|
||||
* @param query the query document that specifies the criteria used to find a record
|
||||
* @param fields the document that specifies the fields to be returned
|
||||
@@ -1211,15 +1304,11 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
|
||||
/**
|
||||
* Map the results of an ad-hoc query on the default MongoDB collection to a List of the specified type.
|
||||
* <p/>
|
||||
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
|
||||
* configured otherwise, an instance of SimpleMongoConverter will be used.
|
||||
* <p/>
|
||||
* The query document is specified as a standard DBObject and so is the fields specification.
|
||||
* <p/>
|
||||
* Can be overridden by subclasses.
|
||||
*
|
||||
* Map the results of an ad-hoc query on the default MongoDB collection to a List of the specified type. The object is
|
||||
* converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless configured
|
||||
* otherwise, an instance of SimpleMongoConverter will be used. The query document is specified as a standard DBObject
|
||||
* and so is the fields specification. Can be overridden by subclasses.
|
||||
*
|
||||
* @param collectionName name of the collection to retrieve the objects from
|
||||
* @param query the query document that specifies the criteria used to find a record
|
||||
* @param fields the document that specifies the fields to be returned
|
||||
@@ -1236,20 +1325,22 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
protected <S, T> List<T> doFind(String collectionName, DBObject query, DBObject fields, Class<S> entityClass,
|
||||
CursorPreparer preparer, DbObjectCallback<T> objectCallback) {
|
||||
|
||||
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass);
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("find using query: " + query + " fields: " + fields + " for class: " + entityClass
|
||||
+ " in collection: " + collectionName);
|
||||
LOGGER.debug(String.format("find using query: %s fields: %s for class: %s in collection: %s",
|
||||
serializeToJsonSafely(query), fields, entityClass, collectionName));
|
||||
}
|
||||
|
||||
return executeFindMultiInternal(new FindCallback(mapper.getMappedObject(query, entity), fields), preparer,
|
||||
objectCallback, collectionName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Map the results of an ad-hoc query on the default MongoDB collection to a List using the template's converter.
|
||||
* <p/>
|
||||
* The query document is specified as a standard DBObject and so is the fields specification.
|
||||
*
|
||||
* Map the results of an ad-hoc query on the default MongoDB collection to a List using the template's converter. The
|
||||
* query document is specified as a standard DBObject and so is the fields specification.
|
||||
*
|
||||
* @param collectionName name of the collection to retrieve the objects from
|
||||
* @param query the query document that specifies the criteria used to find a record
|
||||
* @param fields the document that specifies the fields to be returned
|
||||
@@ -1288,7 +1379,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
* The first document that matches the query is returned and also removed from the collection in the database.
|
||||
* <p/>
|
||||
* The query document is specified as a standard DBObject and so is the fields specification.
|
||||
*
|
||||
*
|
||||
* @param collectionName name of the collection to retrieve the objects from
|
||||
* @param query the query document that specifies the criteria used to find a record
|
||||
* @param entityClass the parameterized type of the returned list.
|
||||
@@ -1335,7 +1426,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
/**
|
||||
* Populates the id property of the saved object, if it's not set already.
|
||||
*
|
||||
*
|
||||
* @param savedObject
|
||||
* @param id
|
||||
*/
|
||||
@@ -1345,6 +1436,12 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
return;
|
||||
}
|
||||
|
||||
if (savedObject instanceof BasicDBObject) {
|
||||
DBObject dbObject = (DBObject) savedObject;
|
||||
dbObject.put(ID_FIELD, id);
|
||||
return;
|
||||
}
|
||||
|
||||
MongoPersistentProperty idProp = getIdPropertyFor(savedObject.getClass());
|
||||
|
||||
if (idProp == null) {
|
||||
@@ -1354,21 +1451,13 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
ConversionService conversionService = mongoConverter.getConversionService();
|
||||
BeanWrapper<PersistentEntity<Object, ?>, Object> wrapper = BeanWrapper.create(savedObject, conversionService);
|
||||
|
||||
try {
|
||||
Object idValue = wrapper.getProperty(idProp, idProp.getType(), true);
|
||||
|
||||
Object idValue = wrapper.getProperty(idProp, idProp.getType(), true);
|
||||
|
||||
if (idValue != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
wrapper.setProperty(idProp, id);
|
||||
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new MappingException(e.getMessage(), e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new MappingException(e.getMessage(), e);
|
||||
if (idValue != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
wrapper.setProperty(idProp, id);
|
||||
}
|
||||
|
||||
private DBCollection getAndPrepareCollection(DB db, String collectionName) {
|
||||
@@ -1388,7 +1477,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
* <li>Execute the given {@link ConnectionCallback} for a {@link DBObject}.</li>
|
||||
* <li>Apply the given {@link DbObjectCallback} to each of the {@link DBObject}s to obtain the result.</li>
|
||||
* <ol>
|
||||
*
|
||||
*
|
||||
* @param <T>
|
||||
* @param collectionCallback the callback to retrieve the {@link DBObject} with
|
||||
* @param objectCallback the {@link DbObjectCallback} to transform {@link DBObject}s into the actual domain type
|
||||
@@ -1429,19 +1518,32 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
CursorPreparer preparer, DbObjectCallback<T> objectCallback, String collectionName) {
|
||||
|
||||
try {
|
||||
DBCursor cursor = collectionCallback.doInCollection(getAndPrepareCollection(getDb(), collectionName));
|
||||
|
||||
if (preparer != null) {
|
||||
cursor = preparer.prepare(cursor);
|
||||
DBCursor cursor = null;
|
||||
|
||||
try {
|
||||
|
||||
cursor = collectionCallback.doInCollection(getAndPrepareCollection(getDb(), collectionName));
|
||||
|
||||
if (preparer != null) {
|
||||
cursor = preparer.prepare(cursor);
|
||||
}
|
||||
|
||||
List<T> result = new ArrayList<T>();
|
||||
|
||||
while (cursor.hasNext()) {
|
||||
DBObject object = cursor.next();
|
||||
result.add(objectCallback.doWith(object));
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
} finally {
|
||||
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
List<T> result = new ArrayList<T>();
|
||||
|
||||
for (DBObject object : cursor) {
|
||||
result.add(objectCallback.doWith(object));
|
||||
}
|
||||
|
||||
return result;
|
||||
} catch (RuntimeException e) {
|
||||
throw potentiallyConvertRuntimeException(e);
|
||||
}
|
||||
@@ -1451,15 +1553,27 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
DocumentCallbackHandler callbackHandler, String collectionName) {
|
||||
|
||||
try {
|
||||
DBCursor cursor = collectionCallback.doInCollection(getAndPrepareCollection(getDb(), collectionName));
|
||||
|
||||
if (preparer != null) {
|
||||
cursor = preparer.prepare(cursor);
|
||||
DBCursor cursor = null;
|
||||
|
||||
try {
|
||||
cursor = collectionCallback.doInCollection(getAndPrepareCollection(getDb(), collectionName));
|
||||
|
||||
if (preparer != null) {
|
||||
cursor = preparer.prepare(cursor);
|
||||
}
|
||||
|
||||
while (cursor.hasNext()) {
|
||||
DBObject dbobject = cursor.next();
|
||||
callbackHandler.processDocument(dbobject);
|
||||
}
|
||||
|
||||
} finally {
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
for (DBObject dbobject : cursor) {
|
||||
callbackHandler.processDocument(dbobject);
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
throw potentiallyConvertRuntimeException(e);
|
||||
}
|
||||
@@ -1470,7 +1584,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
|
||||
private MongoPersistentProperty getIdPropertyFor(Class<?> type) {
|
||||
return mappingContext.getPersistentEntity(type).getIdProperty();
|
||||
MongoPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(type);
|
||||
return persistentEntity == null ? null : persistentEntity.getIdProperty();
|
||||
}
|
||||
|
||||
private <T> String determineEntityCollectionName(T obj) {
|
||||
@@ -1497,37 +1612,45 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks and handles any errors.
|
||||
* <p/>
|
||||
* Current implementation logs errors. Future version may make this configurable to log warning, errors or throw
|
||||
* exception.
|
||||
* Handles {@link WriteResult} errors based on the configured {@link WriteResultChecking}.
|
||||
*
|
||||
* @param writeResult
|
||||
* @param query
|
||||
* @param operation
|
||||
*/
|
||||
protected void handleAnyWriteResultErrors(WriteResult wr, DBObject query, String operation) {
|
||||
protected void handleAnyWriteResultErrors(WriteResult writeResult, DBObject query, MongoActionOperation operation) {
|
||||
|
||||
if (WriteResultChecking.NONE == this.writeResultChecking) {
|
||||
if (writeResultChecking == WriteResultChecking.NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
String error = wr.getError();
|
||||
String error = writeResult.getError();
|
||||
|
||||
if (error != null) {
|
||||
String message;
|
||||
if (operation.equals("insert") || operation.equals("save")) {
|
||||
// assuming the insert operations will begin with insert string
|
||||
if (error == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String message;
|
||||
|
||||
switch (operation) {
|
||||
|
||||
case INSERT:
|
||||
case SAVE:
|
||||
message = String.format("Insert/Save for %s failed: %s", query, error);
|
||||
} else if (operation.equals("insert_list")) {
|
||||
break;
|
||||
case INSERT_LIST:
|
||||
message = String.format("Insert list failed: %s", error);
|
||||
} else {
|
||||
break;
|
||||
default:
|
||||
message = String.format("Execution of %s%s failed: %s", operation,
|
||||
query == null ? "" : "' using '" + query.toString() + "' query", error);
|
||||
}
|
||||
query == null ? "" : " using query " + query.toString(), error);
|
||||
}
|
||||
|
||||
if (WriteResultChecking.EXCEPTION == this.writeResultChecking) {
|
||||
throw new DataIntegrityViolationException(message);
|
||||
} else {
|
||||
LOGGER.error(message);
|
||||
return;
|
||||
}
|
||||
if (writeResultChecking == WriteResultChecking.EXCEPTION) {
|
||||
throw new DataIntegrityViolationException(message);
|
||||
} else {
|
||||
LOGGER.error(message);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1615,7 +1738,6 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
private static class FindCallback implements CollectionCallback<DBCursor> {
|
||||
|
||||
private final DBObject query;
|
||||
|
||||
private final DBObject fields;
|
||||
|
||||
public FindCallback(DBObject query) {
|
||||
@@ -1723,12 +1845,13 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
}
|
||||
|
||||
private class DefaultWriteConcernResolver implements WriteConcernResolver {
|
||||
private enum DefaultWriteConcernResolver implements WriteConcernResolver {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
public WriteConcern resolve(MongoAction action) {
|
||||
return action.getDefaultWriteConcern();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class QueryCursorPreparer implements CursorPreparer {
|
||||
@@ -1792,7 +1915,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
* Creates a new {@link GeoNearResultDbObjectCallback} using the given {@link DbObjectCallback} delegate for
|
||||
* {@link GeoResult} content unmarshalling.
|
||||
*
|
||||
* @param delegate
|
||||
* @param delegate must not be {@literal null}.
|
||||
*/
|
||||
public GeoNearResultDbObjectCallback(DbObjectCallback<T> delegate, Metric metric) {
|
||||
Assert.notNull(delegate);
|
||||
|
||||
@@ -47,7 +47,7 @@ public class SimpleMongoDbFactory implements DisposableBean, MongoDbFactory {
|
||||
* Create an instance of {@link SimpleMongoDbFactory} given the {@link Mongo} instance and database name.
|
||||
*
|
||||
* @param mongo Mongo instance, must not be {@literal null}.
|
||||
* @param databaseName database name, not be {@literal null}.
|
||||
* @param databaseName database name, not be {@literal null} or empty.
|
||||
*/
|
||||
public SimpleMongoDbFactory(Mongo mongo, String databaseName) {
|
||||
this(mongo, databaseName, UserCredentials.NO_CREDENTIALS, false);
|
||||
@@ -57,7 +57,7 @@ public class SimpleMongoDbFactory implements DisposableBean, MongoDbFactory {
|
||||
* Create an instance of SimpleMongoDbFactory given the Mongo instance, database name, and username/password
|
||||
*
|
||||
* @param mongo Mongo instance, must not be {@literal null}.
|
||||
* @param databaseName Database name, must not be {@literal null}.
|
||||
* @param databaseName Database name, must not be {@literal null} or empty.
|
||||
* @param credentials username and password.
|
||||
*/
|
||||
public SimpleMongoDbFactory(Mongo mongo, String databaseName, UserCredentials credentials) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
* Copyright 2011-2012 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.
|
||||
@@ -13,27 +13,25 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.mongodb.core;
|
||||
|
||||
import com.mongodb.WriteConcern;
|
||||
|
||||
/**
|
||||
* A strategy interface to determine the WriteConcern to use for a given MongoDbAction.
|
||||
*
|
||||
* Return the passed in default WriteConcern (a property on MongoAction) if no determination can be made.
|
||||
* A strategy interface to determine the {@link WriteConcern} to use for a given {@link MongoAction}. Return the passed
|
||||
* in default {@link WriteConcern} (a property on {@link MongoAction}) if no determination can be made.
|
||||
*
|
||||
* @author Mark Pollack
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface WriteConcernResolver {
|
||||
|
||||
/**
|
||||
* Resolve the WriteConcern given the MongoAction
|
||||
* Resolve the {@link WriteConcern} given the {@link MongoAction}.
|
||||
*
|
||||
* @param action describes the context of the Mongo action. Contains a default WriteConcern to use if one should not
|
||||
* be resolved.
|
||||
* @return a WriteConcern based on the passed in MongoAction value, maybe null
|
||||
* @param action describes the context of the Mongo action. Contains a default {@link WriteConcern} to use if one
|
||||
* should not be resolved.
|
||||
* @return a {@link WriteConcern} based on the passed in {@link MongoAction} value, maybe {@literal null}.
|
||||
*/
|
||||
WriteConcern resolve(MongoAction action);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,28 @@
|
||||
/*
|
||||
* Copyright 2012 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;
|
||||
|
||||
/**
|
||||
* Enum to represent how strict the check of {@link com.mongodb.WriteResult} shall be. It can either be skipped entirely
|
||||
* (use {@link #NONE}), or errors can be logged ({@link #LOG}) or cause an exception to be thrown {@link #EXCEPTION}.
|
||||
*
|
||||
* @author Thomas Risberg
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public enum WriteResultChecking {
|
||||
|
||||
NONE, LOG, EXCEPTION
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) 2011 by the original author(s).
|
||||
* Copyright 2011-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -13,7 +13,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import java.math.BigInteger;
|
||||
@@ -33,8 +32,8 @@ import org.springframework.data.mongodb.core.convert.MongoConverters.StringToObj
|
||||
* Base class for {@link MongoConverter} implementations. Sets up a {@link GenericConversionService} and populates basic
|
||||
* converters. Allows registering {@link CustomConversions}.
|
||||
*
|
||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||
* @author Oliver Gierke ogierke@vmware.com
|
||||
* @author Jon Brisbin
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public abstract class AbstractMongoConverter implements MongoConverter, InitializingBean {
|
||||
|
||||
@@ -94,6 +93,14 @@ public abstract class AbstractMongoConverter implements MongoConverter, Initiali
|
||||
conversions.registerConvertersIn(conversionService);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.convert.MongoWriter#convertToMongoType(java.lang.Object)
|
||||
*/
|
||||
public Object convertToMongoType(Object obj) {
|
||||
return convertToMongoType(obj, null);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.core.convert.MongoConverter#getConversionService()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2012 by the original author(s).
|
||||
* Copyright 2011-2013 by the original author(s).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
@@ -253,13 +252,9 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
public void doWithAssociation(Association<MongoPersistentProperty> association) {
|
||||
MongoPersistentProperty inverseProp = association.getInverse();
|
||||
Object obj = getValueInternal(inverseProp, dbo, evaluator, result);
|
||||
try {
|
||||
wrapper.setProperty(inverseProp, obj);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new MappingException(e.getMessage(), e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new MappingException(e.getMessage(), e);
|
||||
}
|
||||
|
||||
wrapper.setProperty(inverseProp, obj);
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
@@ -351,13 +346,14 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
}
|
||||
|
||||
final BeanWrapper<MongoPersistentEntity<Object>, Object> wrapper = BeanWrapper.create(obj, conversionService);
|
||||
|
||||
// Write the ID
|
||||
final MongoPersistentProperty idProperty = entity.getIdProperty();
|
||||
|
||||
if (!dbo.containsField("_id") && null != idProperty) {
|
||||
|
||||
boolean fieldAccessOnly = idProperty.usePropertyAccess() ? false : useFieldAccessOnly;
|
||||
|
||||
try {
|
||||
Object id = wrapper.getProperty(idProperty, Object.class, useFieldAccessOnly);
|
||||
Object id = wrapper.getProperty(idProperty, Object.class, fieldAccessOnly);
|
||||
dbo.put("_id", idMapper.convertId(id));
|
||||
} catch (ConversionException ignored) {
|
||||
}
|
||||
@@ -371,7 +367,9 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
return;
|
||||
}
|
||||
|
||||
Object propertyObj = wrapper.getProperty(prop, prop.getType(), useFieldAccessOnly);
|
||||
boolean fieldAccessOnly = prop.usePropertyAccess() ? false : useFieldAccessOnly;
|
||||
|
||||
Object propertyObj = wrapper.getProperty(prop, prop.getType(), fieldAccessOnly);
|
||||
|
||||
if (null != propertyObj) {
|
||||
if (!conversions.isSimpleType(propertyObj.getClass())) {
|
||||
@@ -676,6 +674,10 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
|
||||
Assert.notNull(target);
|
||||
|
||||
if (target instanceof DBRef) {
|
||||
return (DBRef) target;
|
||||
}
|
||||
|
||||
MongoPersistentEntity<?> targetEntity = mappingContext.getPersistentEntity(target.getClass());
|
||||
|
||||
if (null == targetEntity) {
|
||||
@@ -720,11 +722,12 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
|
||||
Assert.notNull(targetType);
|
||||
|
||||
Class<?> collectionType = targetType.getType();
|
||||
|
||||
if (sourceValue.isEmpty()) {
|
||||
return new HashSet<Object>();
|
||||
return getPotentiallyConvertedSimpleRead(new HashSet<Object>(), collectionType);
|
||||
}
|
||||
|
||||
Class<?> collectionType = targetType.getType();
|
||||
collectionType = Collection.class.isAssignableFrom(collectionType) ? collectionType : List.class;
|
||||
|
||||
Collection<Object> items = targetType.getType().isArray() ? new ArrayList<Object>() : CollectionFactory
|
||||
@@ -810,8 +813,12 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
return rootList;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.convert.MongoWriter#convertToMongoType(java.lang.Object, org.springframework.data.util.TypeInformation)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object convertToMongoType(Object obj) {
|
||||
public Object convertToMongoType(Object obj, TypeInformation<?> typeInformation) {
|
||||
|
||||
if (obj == null) {
|
||||
return null;
|
||||
@@ -858,7 +865,12 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
|
||||
DBObject newDbo = new BasicDBObject();
|
||||
this.write(obj, newDbo);
|
||||
return removeTypeInfoRecursively(newDbo);
|
||||
|
||||
if (typeInformation == null) {
|
||||
return removeTypeInfoRecursively(newDbo);
|
||||
}
|
||||
|
||||
return !obj.getClass().equals(typeInformation.getType()) ? newDbo : removeTypeInfoRecursively(newDbo);
|
||||
}
|
||||
|
||||
public BasicDBList maybeConvertList(Iterable<?> source) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2012 the original author or authors.
|
||||
* Copyright 2010-2013 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.
|
||||
@@ -17,6 +17,7 @@ package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import org.springframework.data.convert.EntityWriter;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.DBRef;
|
||||
@@ -35,11 +36,21 @@ public interface MongoWriter<T> extends EntityWriter<T, DBObject> {
|
||||
* Converts the given object into one Mongo will be able to store natively. If the given object can already be stored
|
||||
* as is, no conversion will happen.
|
||||
*
|
||||
* @param obj
|
||||
* @param obj can be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
Object convertToMongoType(Object obj);
|
||||
|
||||
/**
|
||||
* Converts the given object into one Mongo will be able to store natively but retains the type information in case
|
||||
* the given {@link TypeInformation} differs from the given object type.
|
||||
*
|
||||
* @param obj can be {@literal null}.
|
||||
* @param typeInformation can be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
Object convertToMongoType(Object obj, TypeInformation<?> typeInformation);
|
||||
|
||||
/**
|
||||
* Creates a {@link DBRef} to refer to the given object.
|
||||
*
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) 2011 by the original author(s).
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -17,14 +17,16 @@ package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.bson.types.BasicBSONList;
|
||||
import org.bson.types.ObjectId;
|
||||
import org.springframework.core.convert.ConversionException;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
import org.springframework.data.mapping.PropertyPath;
|
||||
import org.springframework.data.mapping.PropertyReferenceException;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mapping.context.PersistentPropertyPath;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -32,11 +34,12 @@ import org.springframework.util.Assert;
|
||||
import com.mongodb.BasicDBList;
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.DBRef;
|
||||
|
||||
/**
|
||||
* A helper class to encapsulate any modifications of a Query object before it gets submitted to the database.
|
||||
*
|
||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||
* @author Jon Brisbin
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class QueryMapper {
|
||||
@@ -46,6 +49,7 @@ public class QueryMapper {
|
||||
|
||||
private final ConversionService conversionService;
|
||||
private final MongoConverter converter;
|
||||
private final MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
|
||||
|
||||
/**
|
||||
* Creates a new {@link QueryMapper} with the given {@link MongoConverter}.
|
||||
@@ -53,9 +57,12 @@ public class QueryMapper {
|
||||
* @param converter must not be {@literal null}.
|
||||
*/
|
||||
public QueryMapper(MongoConverter converter) {
|
||||
|
||||
Assert.notNull(converter);
|
||||
|
||||
this.conversionService = converter.getConversionService();
|
||||
this.converter = converter;
|
||||
this.mappingContext = converter.getMappingContext();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,47 +75,151 @@ public class QueryMapper {
|
||||
*/
|
||||
public DBObject getMappedObject(DBObject query, MongoPersistentEntity<?> entity) {
|
||||
|
||||
DBObject newDbo = new BasicDBObject();
|
||||
if (Keyword.isKeyword(query)) {
|
||||
return getMappedKeyword(new Keyword(query), entity);
|
||||
}
|
||||
|
||||
DBObject result = new BasicDBObject();
|
||||
|
||||
for (String key : query.keySet()) {
|
||||
|
||||
String newKey = key;
|
||||
MongoPersistentProperty targetProperty = getTargetProperty(key, entity);
|
||||
String newKey = determineKey(key, entity);
|
||||
Object value = query.get(key);
|
||||
|
||||
if (isIdKey(key, entity)) {
|
||||
if (value instanceof DBObject) {
|
||||
DBObject valueDbo = (DBObject) value;
|
||||
if (valueDbo.containsField("$in") || valueDbo.containsField("$nin")) {
|
||||
String inKey = valueDbo.containsField("$in") ? "$in" : "$nin";
|
||||
List<Object> ids = new ArrayList<Object>();
|
||||
for (Object id : (Iterable<?>) valueDbo.get(inKey)) {
|
||||
ids.add(convertId(id));
|
||||
}
|
||||
valueDbo.put(inKey, ids.toArray(new Object[ids.size()]));
|
||||
} else {
|
||||
value = getMappedObject((DBObject) value, null);
|
||||
}
|
||||
} else {
|
||||
value = convertId(value);
|
||||
}
|
||||
newKey = "_id";
|
||||
} else if (key.matches(N_OR_PATTERN)) {
|
||||
// $or/$nor
|
||||
Iterable<?> conditions = (Iterable<?>) value;
|
||||
BasicBSONList newConditions = new BasicBSONList();
|
||||
Iterator<?> iter = conditions.iterator();
|
||||
while (iter.hasNext()) {
|
||||
newConditions.add(getMappedObject((DBObject) iter.next(), null));
|
||||
}
|
||||
value = newConditions;
|
||||
} else if (key.equals("$ne")) {
|
||||
value = convertId(value);
|
||||
}
|
||||
|
||||
newDbo.put(newKey, convertSimpleOrDBObject(value, null));
|
||||
result.put(newKey, getMappedValue(value, targetProperty, newKey));
|
||||
}
|
||||
|
||||
return newDbo;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the given {@link DBObject} representing a keyword by mapping the keyword's value.
|
||||
*
|
||||
* @param query the {@link DBObject} representing a keyword (e.g. {@code $ne : … } )
|
||||
* @param entity
|
||||
* @return
|
||||
*/
|
||||
private DBObject getMappedKeyword(Keyword query, MongoPersistentEntity<?> entity) {
|
||||
|
||||
// $or/$nor
|
||||
if (query.key.matches(N_OR_PATTERN)) {
|
||||
|
||||
Iterable<?> conditions = (Iterable<?>) query.value;
|
||||
BasicDBList newConditions = new BasicDBList();
|
||||
|
||||
for (Object condition : conditions) {
|
||||
newConditions.add(getMappedObject((DBObject) condition, entity));
|
||||
}
|
||||
|
||||
return new BasicDBObject(query.key, newConditions);
|
||||
}
|
||||
|
||||
return new BasicDBObject(query.key, convertSimpleOrDBObject(query.value, entity));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the mapped keyword considered defining a criteria for the given property.
|
||||
*
|
||||
* @param keyword
|
||||
* @param property
|
||||
* @return
|
||||
*/
|
||||
public DBObject getMappedKeyword(Keyword keyword, MongoPersistentProperty property) {
|
||||
|
||||
if (property.isAssociation()) {
|
||||
convertAssociation(keyword.value, property);
|
||||
}
|
||||
|
||||
return new BasicDBObject(keyword.key, getMappedValue(keyword.value, property, keyword.key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the mapped value for the given source object assuming it's a value for the given
|
||||
* {@link MongoPersistentProperty}.
|
||||
*
|
||||
* @param source the source object to be mapped
|
||||
* @param property the property the value is a value for
|
||||
* @param newKey the key the value will be bound to eventually
|
||||
* @return
|
||||
*/
|
||||
private Object getMappedValue(Object source, MongoPersistentProperty property, String newKey) {
|
||||
|
||||
if (property == null) {
|
||||
return convertSimpleOrDBObject(source, null);
|
||||
}
|
||||
|
||||
if (property.isIdProperty() || "_id".equals(newKey)) {
|
||||
|
||||
if (source instanceof DBObject) {
|
||||
DBObject valueDbo = (DBObject) source;
|
||||
if (valueDbo.containsField("$in") || valueDbo.containsField("$nin")) {
|
||||
String inKey = valueDbo.containsField("$in") ? "$in" : "$nin";
|
||||
List<Object> ids = new ArrayList<Object>();
|
||||
for (Object id : (Iterable<?>) valueDbo.get(inKey)) {
|
||||
ids.add(convertId(id));
|
||||
}
|
||||
valueDbo.put(inKey, ids.toArray(new Object[ids.size()]));
|
||||
} else if (valueDbo.containsField("$ne")) {
|
||||
valueDbo.put("$ne", convertId(valueDbo.get("$ne")));
|
||||
} else {
|
||||
return getMappedObject((DBObject) source, null);
|
||||
}
|
||||
|
||||
return valueDbo;
|
||||
|
||||
} else {
|
||||
return convertId(source);
|
||||
}
|
||||
}
|
||||
|
||||
if (property.isAssociation()) {
|
||||
return Keyword.isKeyword(source) ? getMappedKeyword(new Keyword(source), property) : convertAssociation(source,
|
||||
property);
|
||||
}
|
||||
|
||||
return convertSimpleOrDBObject(source, mappingContext.getPersistentEntity(property));
|
||||
}
|
||||
|
||||
private MongoPersistentProperty getTargetProperty(String key, MongoPersistentEntity<?> entity) {
|
||||
|
||||
if (isIdKey(key, entity)) {
|
||||
return entity.getIdProperty();
|
||||
}
|
||||
|
||||
PersistentPropertyPath<MongoPersistentProperty> path = getPath(key, entity);
|
||||
return path == null ? null : path.getLeafProperty();
|
||||
}
|
||||
|
||||
private PersistentPropertyPath<MongoPersistentProperty> getPath(String key, MongoPersistentEntity<?> entity) {
|
||||
|
||||
if (entity == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
PropertyPath path = PropertyPath.from(key, entity.getTypeInformation());
|
||||
return mappingContext.getPersistentPropertyPath(path);
|
||||
} catch (PropertyReferenceException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the translated key assuming the given one is a propert (path) reference.
|
||||
*
|
||||
* @param key the source key
|
||||
* @param entity the base entity
|
||||
* @return the translated key
|
||||
*/
|
||||
private String determineKey(String key, MongoPersistentEntity<?> entity) {
|
||||
|
||||
if (entity == null && DEFAULT_ID_NAMES.contains(key)) {
|
||||
return "_id";
|
||||
}
|
||||
|
||||
PersistentPropertyPath<MongoPersistentProperty> path = getPath(key, entity);
|
||||
return path == null ? key : path.toDotPath(MongoPersistentProperty.PropertyToFieldNameConverter.INSTANCE);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -131,6 +242,30 @@ public class QueryMapper {
|
||||
return converter.convertToMongoType(source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given source assuming it's actually an association to anoter object.
|
||||
*
|
||||
* @param source
|
||||
* @param property
|
||||
* @return
|
||||
*/
|
||||
private Object convertAssociation(Object source, MongoPersistentProperty property) {
|
||||
|
||||
if (property == null || !property.isAssociation()) {
|
||||
return source;
|
||||
}
|
||||
|
||||
if (source instanceof Iterable) {
|
||||
BasicDBList result = new BasicDBList();
|
||||
for (Object element : (Iterable<?>) source) {
|
||||
result.add(element instanceof DBRef ? element : converter.toDBRef(element, property));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
return source == null || source instanceof DBRef ? source : converter.toDBRef(source, property);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given key will be considered an id key.
|
||||
*
|
||||
@@ -169,4 +304,44 @@ public class QueryMapper {
|
||||
|
||||
return converter.convertToMongoType(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Value object to capture a query keyword representation.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
private static class Keyword {
|
||||
|
||||
String key;
|
||||
Object value;
|
||||
|
||||
Keyword(Object source) {
|
||||
|
||||
Assert.isInstanceOf(DBObject.class, source);
|
||||
|
||||
DBObject value = (DBObject) source;
|
||||
|
||||
Assert.isTrue(value.keySet().size() == 1, "Keyword must have a single key only!");
|
||||
|
||||
this.key = value.keySet().iterator().next();
|
||||
this.value = value.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given value actually represents a keyword. If this returns {@literal true} it's safe to call
|
||||
* the constructor.
|
||||
*
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
static boolean isKeyword(Object value) {
|
||||
|
||||
if (!(value instanceof DBObject)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DBObject dbObject = (DBObject) value;
|
||||
return dbObject.keySet().size() == 1 && dbObject.keySet().iterator().next().startsWith("$");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) 2011 by the original author(s).
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -13,37 +13,51 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.mongodb.core.index;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.data.mapping.event.MappingContextEvent;
|
||||
import org.springframework.data.mapping.context.MappingContextEvent;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
import org.springframework.data.mongodb.core.mapping.event.AfterLoadEvent;
|
||||
import org.springframework.data.mongodb.core.mapping.event.AfterSaveEvent;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* An implementation of ApplicationEventPublisher that will only fire MappingContextEvents for use by the index creator
|
||||
* when MongoTemplate is used 'stand-alone', that is not declared inside a Spring ApplicationContext.
|
||||
* An implementation of ApplicationEventPublisher that will only fire {@link MappingContextEvent}s for use by the index
|
||||
* creator when MongoTemplate is used 'stand-alone', that is not declared inside a Spring {@link ApplicationContext}.
|
||||
* Declare {@link MongoTemplate} inside an {@link ApplicationContext} to enable the publishing of all persistence events
|
||||
* such as {@link AfterLoadEvent}, {@link AfterSaveEvent}, etc.
|
||||
*
|
||||
* Declare MongoTemplate inside an ApplicationContext to enable the publishing of all persistence events such as
|
||||
* {@link AfterLoadEvent}, {@link AfterSaveEvent}, etc.
|
||||
*
|
||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||
* @author Jon Brisbin
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class MongoMappingEventPublisher implements ApplicationEventPublisher {
|
||||
|
||||
private MongoPersistentEntityIndexCreator indexCreator;
|
||||
private final MongoPersistentEntityIndexCreator indexCreator;
|
||||
|
||||
/**
|
||||
* Creates a new {@link MongoMappingEventPublisher} for the given {@link MongoPersistentEntityIndexCreator}.
|
||||
*
|
||||
* @param indexCreator must not be {@literal null}.
|
||||
*/
|
||||
public MongoMappingEventPublisher(MongoPersistentEntityIndexCreator indexCreator) {
|
||||
|
||||
Assert.notNull(indexCreator);
|
||||
this.indexCreator = indexCreator;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.context.ApplicationEventPublisher#publishEvent(org.springframework.context.ApplicationEvent)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void publishEvent(ApplicationEvent event) {
|
||||
if (event instanceof MappingContextEvent) {
|
||||
indexCreator
|
||||
.onApplicationEvent((MappingContextEvent<MongoPersistentEntity<MongoPersistentProperty>, MongoPersistentProperty>) event);
|
||||
indexCreator.onApplicationEvent((MappingContextEvent<MongoPersistentEntity<?>, MongoPersistentProperty>) event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,8 @@ import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
import org.springframework.data.mapping.PropertyHandler;
|
||||
import org.springframework.data.mapping.event.MappingContextEvent;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mapping.context.MappingContextEvent;
|
||||
import org.springframework.data.mongodb.MongoDbFactory;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
@@ -44,25 +45,28 @@ import com.mongodb.util.JSON;
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class MongoPersistentEntityIndexCreator implements
|
||||
ApplicationListener<MappingContextEvent<MongoPersistentEntity<MongoPersistentProperty>, MongoPersistentProperty>> {
|
||||
ApplicationListener<MappingContextEvent<MongoPersistentEntity<?>, MongoPersistentProperty>> {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(MongoPersistentEntityIndexCreator.class);
|
||||
|
||||
private final Map<Class<?>, Boolean> classesSeen = new ConcurrentHashMap<Class<?>, Boolean>();
|
||||
private final MongoDbFactory mongoDbFactory;
|
||||
private final MongoMappingContext mappingContext;
|
||||
|
||||
/**
|
||||
* Creats a new {@link MongoPersistentEntityIndexCreator} for the given {@link MongoMappingContext} and
|
||||
* {@link MongoDbFactory}.
|
||||
*
|
||||
* @param mappingContext must not be {@@iteral null}
|
||||
* @param mongoDbFactory must not be {@@iteral null}
|
||||
* @param mappingContext must not be {@literal null}
|
||||
* @param mongoDbFactory must not be {@literal null}
|
||||
*/
|
||||
public MongoPersistentEntityIndexCreator(MongoMappingContext mappingContext, MongoDbFactory mongoDbFactory) {
|
||||
|
||||
Assert.notNull(mongoDbFactory);
|
||||
Assert.notNull(mappingContext);
|
||||
|
||||
this.mongoDbFactory = mongoDbFactory;
|
||||
this.mappingContext = mappingContext;
|
||||
|
||||
for (MongoPersistentEntity<?> entity : mappingContext.getPersistentEntities()) {
|
||||
checkForIndexes(entity);
|
||||
@@ -73,8 +77,11 @@ public class MongoPersistentEntityIndexCreator implements
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
|
||||
*/
|
||||
public void onApplicationEvent(
|
||||
MappingContextEvent<MongoPersistentEntity<MongoPersistentProperty>, MongoPersistentProperty> event) {
|
||||
public void onApplicationEvent(MappingContextEvent<MongoPersistentEntity<?>, MongoPersistentProperty> event) {
|
||||
|
||||
if (!event.wasEmittedBy(mappingContext)) {
|
||||
return;
|
||||
}
|
||||
|
||||
PersistentEntity<?, ?> entity = event.getPersistentEntity();
|
||||
|
||||
@@ -163,6 +170,26 @@ public class MongoPersistentEntityIndexCreator implements
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the current index creator was registered for the given {@link MappingContext}.
|
||||
*
|
||||
* @param context
|
||||
* @return
|
||||
*/
|
||||
public boolean isIndexCreatorFor(MappingContext<?, ?> context) {
|
||||
return this.mappingContext.equals(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers the actual index creation.
|
||||
*
|
||||
* @param collection the collection to create the index in
|
||||
* @param name the name of the index about to be created
|
||||
* @param indexDefinition the index definition
|
||||
* @param unique whether it shall be a unique index
|
||||
* @param dropDups whether to drop duplicates
|
||||
* @param sparse sparse or not
|
||||
*/
|
||||
protected void ensureIndex(String collection, String name, DBObject indexDefinition, boolean unique,
|
||||
boolean dropDups, boolean sparse) {
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) 2011 by the original author(s).
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -13,7 +13,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.mongodb.core.mapping;
|
||||
|
||||
import java.util.Comparator;
|
||||
@@ -23,8 +22,8 @@ import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.expression.BeanFactoryAccessor;
|
||||
import org.springframework.context.expression.BeanFactoryResolver;
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
import org.springframework.data.mapping.model.BasicPersistentEntity;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.mongodb.MongoCollectionUtils;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.expression.Expression;
|
||||
@@ -34,11 +33,12 @@ import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Mongo specific {@link PersistentEntity} implementation that adds Mongo specific meta-data such as the collection name
|
||||
* and the like.
|
||||
* MongoDB specific {@link MongoPersistentEntity} implementation that adds Mongo specific meta-data such as the
|
||||
* collection name and the like.
|
||||
*
|
||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||
* @author Jon Brisbin
|
||||
* @author Oliver Gierke
|
||||
* @author Patryk Wasik
|
||||
*/
|
||||
public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T, MongoPersistentProperty> implements
|
||||
MongoPersistentEntity<T>, ApplicationContextAware {
|
||||
@@ -47,6 +47,8 @@ public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T, Mong
|
||||
private final SpelExpressionParser parser;
|
||||
private final StandardEvaluationContext context;
|
||||
|
||||
private MongoPersistentProperty versionProperty;
|
||||
|
||||
/**
|
||||
* Creates a new {@link BasicMongoPersistentEntity} with the given {@link TypeInformation}. Will default the
|
||||
* collection name to the entities simple type name.
|
||||
@@ -71,20 +73,41 @@ public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T, Mong
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.MutablePersistentEntity#addPersistentProperty(P)
|
||||
*/
|
||||
@Override
|
||||
public void addPersistentProperty(MongoPersistentProperty property) {
|
||||
|
||||
if (property.isVersionProperty()) {
|
||||
|
||||
if (this.versionProperty != null) {
|
||||
throw new MappingException(String.format(
|
||||
"Attempt to add version property %s but already have property %s registered "
|
||||
+ "as version. Check your mapping configuration!", property.getField(), versionProperty.getField()));
|
||||
}
|
||||
|
||||
this.versionProperty = property;
|
||||
}
|
||||
|
||||
super.addPersistentProperty(property);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
|
||||
*/
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
|
||||
context.addPropertyAccessor(new BeanFactoryAccessor());
|
||||
context.setBeanResolver(new BeanFactoryResolver(applicationContext));
|
||||
context.setRootObject(applicationContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the collection the entity should be stored in.
|
||||
*
|
||||
* @return
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.mapping.MongoPersistentEntity#getCollection()
|
||||
*/
|
||||
public String getCollection() {
|
||||
|
||||
@@ -92,6 +115,22 @@ public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T, Mong
|
||||
return expression.getValue(context, String.class);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.mapping.MongoPersistentEntity#getVersionProperty()
|
||||
*/
|
||||
public MongoPersistentProperty getVersionProperty() {
|
||||
return versionProperty;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.mapping.MongoPersistentEntity#hasVersionProperty()
|
||||
*/
|
||||
public boolean hasVersionProperty() {
|
||||
return getVersionProperty() != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Comparator} implementation inspecting the {@link MongoPersistentProperty}'s order.
|
||||
*
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) 2011 by the original author(s).
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -27,14 +27,16 @@ import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.mapping.Association;
|
||||
import org.springframework.data.mapping.model.AnnotationBasedPersistentProperty;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* Mongo specific {@link org.springframework.data.mapping.PersistentProperty} implementation.
|
||||
* MongoDB specific {@link org.springframework.data.mapping.MongoPersistentProperty} implementation.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Patryk Wasik
|
||||
*/
|
||||
public class BasicMongoPersistentProperty extends AnnotationBasedPersistentProperty<MongoPersistentProperty> implements
|
||||
MongoPersistentProperty {
|
||||
@@ -45,6 +47,8 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope
|
||||
private static final Set<Class<?>> SUPPORTED_ID_TYPES = new HashSet<Class<?>>();
|
||||
private static final Set<String> SUPPORTED_ID_PROPERTY_NAMES = new HashSet<String>();
|
||||
|
||||
private static final Field CAUSE_FIELD;
|
||||
|
||||
static {
|
||||
SUPPORTED_ID_TYPES.add(ObjectId.class);
|
||||
SUPPORTED_ID_TYPES.add(String.class);
|
||||
@@ -52,6 +56,8 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope
|
||||
|
||||
SUPPORTED_ID_PROPERTY_NAMES.add("id");
|
||||
SUPPORTED_ID_PROPERTY_NAMES.add("_id");
|
||||
|
||||
CAUSE_FIELD = ReflectionUtils.findField(Throwable.class, "cause");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -112,8 +118,9 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope
|
||||
return annotation != null && StringUtils.hasText(annotation.value()) ? annotation.value() : field.getName();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.core.mapping.MongoPersistentProperty#getFieldOrder()
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.mapping.MongoPersistentProperty#getFieldOrder()
|
||||
*/
|
||||
public int getFieldOrder() {
|
||||
org.springframework.data.mongodb.core.mapping.Field annotation = getField().getAnnotation(
|
||||
@@ -121,25 +128,44 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope
|
||||
return annotation != null ? annotation.order() : Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.AbstractPersistentProperty#createAssociation()
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.model.AbstractPersistentProperty#createAssociation()
|
||||
*/
|
||||
@Override
|
||||
protected Association<MongoPersistentProperty> createAssociation() {
|
||||
return new Association<MongoPersistentProperty>(this, null);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.core.mapping.MongoPersistentProperty#isDbReference()
|
||||
*/
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.mapping.MongoPersistentProperty#isDbReference()
|
||||
*/
|
||||
public boolean isDbReference() {
|
||||
return getField().isAnnotationPresent(DBRef.class);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.core.mapping.MongoPersistentProperty#getDBRef()
|
||||
*/
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.mapping.MongoPersistentProperty#getDBRef()
|
||||
*/
|
||||
public DBRef getDBRef() {
|
||||
return getField().getAnnotation(DBRef.class);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.mapping.MongoPersistentProperty#isVersionProperty()
|
||||
*/
|
||||
public boolean isVersionProperty() {
|
||||
return getField().isAnnotationPresent(Version.class);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.mapping.MongoPersistentProperty#usePropertyAccess()
|
||||
*/
|
||||
public boolean usePropertyAccess() {
|
||||
return CAUSE_FIELD.equals(getField());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) 2011 by the original author(s).
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) 2011 by the original author(s).
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -13,7 +13,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.mongodb.core.mapping;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
@@ -23,12 +22,16 @@ import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.data.mapping.context.AbstractMappingContext;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
|
||||
/**
|
||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||
* @author Oliver Gierke ogierke@vmware.com
|
||||
* Default implementation of a {@link MappingContext} for MongoDB using {@link BasicMongoPersistentEntity} and
|
||||
* {@link BasicMongoPersistentProperty} as primary abstractions.
|
||||
*
|
||||
* @author Jon Brisbin
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class MongoMappingContext extends AbstractMappingContext<BasicMongoPersistentEntity<?>, MongoPersistentProperty>
|
||||
implements ApplicationContextAware {
|
||||
@@ -42,6 +45,15 @@ public class MongoMappingContext extends AbstractMappingContext<BasicMongoPersis
|
||||
setSimpleTypeHolder(MongoSimpleTypes.HOLDER);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.context.AbstractMappingContext#shouldCreatePersistentEntityFor(org.springframework.data.util.TypeInformation)
|
||||
*/
|
||||
@Override
|
||||
protected boolean shouldCreatePersistentEntityFor(TypeInformation<?> type) {
|
||||
return !MongoSimpleTypes.HOLDER.isSimpleType(type.getType());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.AbstractMappingContext#createPersistentProperty(java.lang.reflect.Field, java.beans.PropertyDescriptor, org.springframework.data.mapping.MutablePersistentEntity, org.springframework.data.mapping.SimpleTypeHolder)
|
||||
@@ -72,7 +84,10 @@ public class MongoMappingContext extends AbstractMappingContext<BasicMongoPersis
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
|
||||
*/
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
|
||||
this.context = applicationContext;
|
||||
super.setApplicationContext(applicationContext);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,49 @@
|
||||
/*
|
||||
* Copyright 2011-2012 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.mapping;
|
||||
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
|
||||
/**
|
||||
* MongoDB specific {@link PersistentEntity} abstraction.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Patryk Wasik
|
||||
*/
|
||||
public interface MongoPersistentEntity<T> extends PersistentEntity<T, MongoPersistentProperty> {
|
||||
|
||||
/**
|
||||
* Returns the collection the entity shall be persisted to.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String getCollection();
|
||||
|
||||
/**
|
||||
* Returns the {@link MongoPersistentProperty} that represents the version attribute of an entity. Will not be
|
||||
* {@literal null} if {@link #hasVersionProperty()}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
MongoPersistentProperty getVersionProperty();
|
||||
|
||||
/**
|
||||
* Returns whether the entity has a property representing the version of the entity.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean hasVersionProperty();
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) 2011 by the original author(s).
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -19,9 +19,10 @@ import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.data.mapping.PersistentProperty;
|
||||
|
||||
/**
|
||||
* Mongo specific {@link org.springframework.data.mapping.PersistentProperty} implementation.
|
||||
* MongoDB specific {@link org.springframework.data.mapping.PersistentProperty} extension.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Patryk Wasik
|
||||
*/
|
||||
public interface MongoPersistentProperty extends PersistentProperty<MongoPersistentProperty> {
|
||||
|
||||
@@ -55,6 +56,13 @@ public interface MongoPersistentProperty extends PersistentProperty<MongoPersist
|
||||
*/
|
||||
DBRef getDBRef();
|
||||
|
||||
/**
|
||||
* Returns whether the property is representing the version attribute of an entity.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean isVersionProperty();
|
||||
|
||||
/**
|
||||
* Simple {@link Converter} implementation to transform a {@link MongoPersistentProperty} into its field name.
|
||||
*
|
||||
@@ -72,4 +80,12 @@ public interface MongoPersistentProperty extends PersistentProperty<MongoPersist
|
||||
return source.getFieldName();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether property access shall be used for reading the property value. This means it will use the getter
|
||||
* instead of field access.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean usePropertyAccess();
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) 2011 by the original author(s).
|
||||
* Copyright 2012-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -29,22 +29,25 @@ import org.springframework.data.mongodb.MongoCollectionUtils;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
|
||||
/**
|
||||
*
|
||||
* @deprecated use {@link MongoMappingContext} instead.
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Deprecated
|
||||
public class SimpleMongoMappingContext extends
|
||||
AbstractMappingContext<SimpleMongoMappingContext.SimpleMongoPersistentEntity<?>, MongoPersistentProperty> {
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.BasicMappingContext#createPersistentEntity(org.springframework.data.util.TypeInformation)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.context.AbstractMappingContext#createPersistentEntity(org.springframework.data.util.TypeInformation)
|
||||
*/
|
||||
@Override
|
||||
protected <T> SimpleMongoPersistentEntity<T> createPersistentEntity(TypeInformation<T> typeInformation) {
|
||||
return new SimpleMongoPersistentEntity<T>(typeInformation);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.BasicMappingContext#createPersistentProperty(java.lang.reflect.Field, java.beans.PropertyDescriptor, org.springframework.data.util.TypeInformation, org.springframework.data.mapping.BasicPersistentEntity)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.context.AbstractMappingContext#createPersistentProperty(java.lang.reflect.Field, java.beans.PropertyDescriptor, org.springframework.data.mapping.model.MutablePersistentEntity, org.springframework.data.mapping.model.SimpleTypeHolder)
|
||||
*/
|
||||
@Override
|
||||
protected SimplePersistentProperty createPersistentProperty(Field field, PropertyDescriptor descriptor,
|
||||
@@ -112,6 +115,21 @@ public class SimpleMongoMappingContext extends
|
||||
public DBRef getDBRef() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.core.mapping.MongoPersistentProperty#isVersion()
|
||||
*/
|
||||
public boolean isVersionProperty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.mapping.MongoPersistentProperty#usePropertyAccess()
|
||||
*/
|
||||
public boolean usePropertyAccess() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static class SimpleMongoPersistentEntity<T> extends BasicPersistentEntity<T, MongoPersistentProperty> implements
|
||||
@@ -130,5 +148,20 @@ public class SimpleMongoMappingContext extends
|
||||
public String getCollection() {
|
||||
return MongoCollectionUtils.getPreferredCollectionName(getType());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.core.mapping.MongoPersistentEntity#getVersionProperty()
|
||||
*/
|
||||
public MongoPersistentProperty getVersionProperty() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.mapping.MongoPersistentEntity#hasVersionProperty()
|
||||
*/
|
||||
public boolean hasVersionProperty() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2012 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.mapping;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.*;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Demarcates a property to be used as version field to implement optimistic locking on entities.
|
||||
*
|
||||
* @since 1.4
|
||||
* @author Patryk Wasik
|
||||
*/
|
||||
@Documented
|
||||
@Target({ FIELD })
|
||||
@Retention(RUNTIME)
|
||||
public @interface Version {
|
||||
|
||||
}
|
||||
@@ -25,7 +25,6 @@ import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.bson.BSON;
|
||||
import org.bson.types.BasicBSONList;
|
||||
import org.springframework.data.mongodb.InvalidMongoDbApiUsageException;
|
||||
import org.springframework.data.mongodb.core.geo.Circle;
|
||||
import org.springframework.data.mongodb.core.geo.Point;
|
||||
@@ -33,6 +32,7 @@ import org.springframework.data.mongodb.core.geo.Shape;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import com.mongodb.BasicDBList;
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
@@ -400,7 +400,7 @@ public class Criteria implements CriteriaDefinition {
|
||||
* @param criteria
|
||||
*/
|
||||
public Criteria orOperator(Criteria... criteria) {
|
||||
BasicBSONList bsonList = createCriteriaList(criteria);
|
||||
BasicDBList bsonList = createCriteriaList(criteria);
|
||||
criteriaChain.add(new Criteria("$or").is(bsonList));
|
||||
return this;
|
||||
}
|
||||
@@ -411,7 +411,7 @@ public class Criteria implements CriteriaDefinition {
|
||||
* @param criteria
|
||||
*/
|
||||
public Criteria norOperator(Criteria... criteria) {
|
||||
BasicBSONList bsonList = createCriteriaList(criteria);
|
||||
BasicDBList bsonList = createCriteriaList(criteria);
|
||||
criteriaChain.add(new Criteria("$nor").is(bsonList));
|
||||
return this;
|
||||
}
|
||||
@@ -422,7 +422,7 @@ public class Criteria implements CriteriaDefinition {
|
||||
* @param criteria
|
||||
*/
|
||||
public Criteria andOperator(Criteria... criteria) {
|
||||
BasicBSONList bsonList = createCriteriaList(criteria);
|
||||
BasicDBList bsonList = createCriteriaList(criteria);
|
||||
criteriaChain.add(new Criteria("$and").is(bsonList));
|
||||
return this;
|
||||
}
|
||||
@@ -478,8 +478,8 @@ public class Criteria implements CriteriaDefinition {
|
||||
return queryCriteria;
|
||||
}
|
||||
|
||||
private BasicBSONList createCriteriaList(Criteria[] criteria) {
|
||||
BasicBSONList bsonList = new BasicBSONList();
|
||||
private BasicDBList createCriteriaList(Criteria[] criteria) {
|
||||
BasicDBList bsonList = new BasicDBList();
|
||||
for (Criteria c : criteria) {
|
||||
bsonList.add(c.getCriteriaObject());
|
||||
}
|
||||
@@ -514,9 +514,28 @@ public class Criteria implements CriteriaDefinition {
|
||||
|
||||
Criteria that = (Criteria) obj;
|
||||
|
||||
boolean keyEqual = this.key == null ? that.key == null : this.key.equals(that.key);
|
||||
boolean criteriaEqual = this.criteria.equals(that.criteria);
|
||||
boolean valueEqual = isEqual(this.isValue, that.isValue);
|
||||
if (this.criteriaChain.size() != that.criteriaChain.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < this.criteriaChain.size(); i++) {
|
||||
|
||||
Criteria left = this.criteriaChain.get(i);
|
||||
Criteria right = that.criteriaChain.get(i);
|
||||
|
||||
if (!simpleCriteriaEquals(left, right)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean simpleCriteriaEquals(Criteria left, Criteria right) {
|
||||
|
||||
boolean keyEqual = left.key == null ? right.key == null : left.key.equals(right.key);
|
||||
boolean criteriaEqual = left.criteria.equals(right.criteria);
|
||||
boolean valueEqual = isEqual(left.isValue, right.isValue);
|
||||
|
||||
return keyEqual && criteriaEqual && valueEqual;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2011 the original author or authors.
|
||||
* Copyright 2010-2012 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.
|
||||
@@ -15,24 +15,32 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.query;
|
||||
|
||||
import static org.springframework.data.mongodb.core.SerializationUtils.*;
|
||||
import static org.springframework.data.mongodb.core.query.SerializationUtils.*;
|
||||
import static org.springframework.util.ObjectUtils.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.mongodb.InvalidMongoDbApiUsageException;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* @author Thomas Risberg
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class Query {
|
||||
|
||||
private LinkedHashMap<String, Criteria> criteria = new LinkedHashMap<String, Criteria>();
|
||||
private Field fieldSpec;
|
||||
private Sort sort;
|
||||
private Sort coreSort;
|
||||
@SuppressWarnings("deprecation")
|
||||
private org.springframework.data.mongodb.core.query.Sort sort;
|
||||
private int skip;
|
||||
private int limit;
|
||||
private String hint;
|
||||
@@ -96,14 +104,61 @@ public class Query {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Sort sort() {
|
||||
/**
|
||||
* Returns a {@link org.springframework.data.mongodb.core.query.Sort} instance to define ordering properties.
|
||||
*
|
||||
* @deprecated use {@link #with(Sort)} instead
|
||||
* @return
|
||||
*/
|
||||
@Deprecated
|
||||
public org.springframework.data.mongodb.core.query.Sort sort() {
|
||||
if (this.sort == null) {
|
||||
this.sort = new Sort();
|
||||
this.sort = new org.springframework.data.mongodb.core.query.Sort();
|
||||
}
|
||||
|
||||
return this.sort;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the given pagination information on the {@link Query} instance. Will transparently set {@code skip} and
|
||||
* {@code limit} as well as applying the {@link Sort} instance defined with the {@link Pageable}.
|
||||
*
|
||||
* @param pageable
|
||||
* @return
|
||||
*/
|
||||
public Query with(Pageable pageable) {
|
||||
|
||||
if (pageable == null) {
|
||||
return this;
|
||||
}
|
||||
|
||||
this.limit = pageable.getPageSize();
|
||||
this.skip = pageable.getOffset();
|
||||
|
||||
return with(pageable.getSort());
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a {@link Sort} to the {@link Query} instance.
|
||||
*
|
||||
* @param sort
|
||||
* @return
|
||||
*/
|
||||
public Query with(Sort sort) {
|
||||
|
||||
if (sort == null) {
|
||||
return this;
|
||||
}
|
||||
|
||||
if (this.coreSort == null) {
|
||||
this.coreSort = sort;
|
||||
} else {
|
||||
this.coreSort = this.coreSort.and(sort);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public DBObject getQueryObject() {
|
||||
DBObject dbo = new BasicDBObject();
|
||||
for (String k : criteria.keySet()) {
|
||||
@@ -121,11 +176,26 @@ public class Query {
|
||||
return fieldSpec.getFieldsObject();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public DBObject getSortObject() {
|
||||
if (this.sort == null) {
|
||||
|
||||
if (this.coreSort == null && this.sort == null) {
|
||||
return null;
|
||||
}
|
||||
return this.sort.getSortObject();
|
||||
|
||||
DBObject dbo = new BasicDBObject();
|
||||
|
||||
if (this.coreSort != null) {
|
||||
for (org.springframework.data.domain.Sort.Order order : this.coreSort) {
|
||||
dbo.put(order.getProperty(), order.isAscending() ? 1 : -1);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.sort != null) {
|
||||
dbo.putAll(this.sort.getSortObject());
|
||||
}
|
||||
|
||||
return dbo;
|
||||
}
|
||||
|
||||
public int getSkip() {
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core;
|
||||
package org.springframework.data.mongodb.core.query;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2011 the original author or authors.
|
||||
* Copyright 2010-2012 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.
|
||||
@@ -21,6 +21,15 @@ import java.util.Map;
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* Helper class to define sorting criterias for a Query instance.
|
||||
*
|
||||
* @author Thomas Risberg
|
||||
* @author Oliver Gierke
|
||||
* @deprecated use {@link org.springframework.data.domain.Sort} instead. See
|
||||
* {@link Query#with(org.springframework.data.domain.Sort)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public class Sort {
|
||||
|
||||
private Map<String, Order> fieldSpec = new LinkedHashMap<String, Order>();
|
||||
@@ -40,7 +49,7 @@ public class Sort {
|
||||
public DBObject getSortObject() {
|
||||
DBObject dbo = new BasicDBObject();
|
||||
for (String k : fieldSpec.keySet()) {
|
||||
dbo.put(k, (fieldSpec.get(k).equals(Order.ASCENDING) ? 1 : -1));
|
||||
dbo.put(k, fieldSpec.get(k).equals(Order.ASCENDING) ? 1 : -1);
|
||||
}
|
||||
return dbo;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2011 the original author or authors.
|
||||
* Copyright 2010-2012 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.
|
||||
@@ -15,13 +15,23 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.query;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DBObject;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
|
||||
/**
|
||||
* Class to easily construct MongoDB update clauses.
|
||||
*
|
||||
* @author Thomas Risberg
|
||||
* @author Mark Pollack
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class Update {
|
||||
|
||||
public enum Position {
|
||||
@@ -40,6 +50,31 @@ public class Update {
|
||||
return new Update().set(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an {@link Update} instance from the given {@link DBObject}. Allows to explicitly exlude fields from making
|
||||
* it into the created {@link Update} object.
|
||||
*
|
||||
* @param object the source {@link DBObject} to create the update from.
|
||||
* @param exclude the fields to exclude.
|
||||
* @return
|
||||
*/
|
||||
public static Update fromDBObject(DBObject object, String... exclude) {
|
||||
|
||||
Update update = new Update();
|
||||
List<String> excludeList = Arrays.asList(exclude);
|
||||
|
||||
for (String key : object.keySet()) {
|
||||
|
||||
if (excludeList.contains(key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
update.set(key, object.get(key));
|
||||
}
|
||||
|
||||
return update;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update using the $set update modifier
|
||||
*
|
||||
|
||||
@@ -19,6 +19,7 @@ import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.core.io.support.ResourcePatternResolver;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
@@ -63,8 +64,10 @@ public interface GridFsOperations extends ResourcePatternResolver {
|
||||
GridFSFile store(InputStream content, String filename, DBObject metadata);
|
||||
|
||||
/**
|
||||
* Returns all files matching the given query.
|
||||
* Returns all files matching the given query. Note, that currently {@link Sort} criterias defined at the
|
||||
* {@link Query} will not be regarded as MongoDB does not support ordering for GridFS file access.
|
||||
*
|
||||
* @see https://jira.mongodb.org/browse/JAVA-431
|
||||
* @param query
|
||||
* @return
|
||||
*/
|
||||
@@ -102,4 +105,4 @@ public interface GridFsOperations extends ResourcePatternResolver {
|
||||
* @see ResourcePatternResolver#getResources(String)
|
||||
*/
|
||||
GridFsResource[] getResources(String filenamePattern);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ package org.springframework.data.mongodb.repository.config;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
@@ -38,6 +39,7 @@ import org.springframework.data.repository.query.QueryLookupStrategy.Key;
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Inherited
|
||||
@Import(MongoRepositoriesRegistrar.class)
|
||||
public @interface EnableMongoRepositories {
|
||||
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.repository.query;
|
||||
|
||||
import static org.springframework.data.mongodb.repository.query.QueryUtils.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
@@ -119,7 +117,7 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
|
||||
|
||||
protected List<?> readCollection(Query query) {
|
||||
|
||||
MongoEntityInformation<?, ?> metadata = method.getEntityInformation();
|
||||
MongoEntityMetadata<?> metadata = method.getEntityInformation();
|
||||
|
||||
String collectionName = metadata.getCollectionName();
|
||||
return operations.find(query, metadata.getJavaType(), collectionName);
|
||||
@@ -145,12 +143,7 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
|
||||
*/
|
||||
@Override
|
||||
public Object execute(Query query) {
|
||||
|
||||
if (pageable != null) {
|
||||
query = applyPagination(query, pageable);
|
||||
}
|
||||
|
||||
return readCollection(query);
|
||||
return readCollection(query.with(pageable));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,11 +175,10 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
Object execute(Query query) {
|
||||
|
||||
MongoEntityInformation<?, ?> metadata = method.getEntityInformation();
|
||||
MongoEntityMetadata<?> metadata = method.getEntityInformation();
|
||||
long count = operations.count(query, metadata.getCollectionName());
|
||||
|
||||
List<?> result = operations.find(applyPagination(query, pageable), metadata.getJavaType(),
|
||||
metadata.getCollectionName());
|
||||
List<?> result = operations.find(query.with(pageable), metadata.getJavaType(), metadata.getCollectionName());
|
||||
|
||||
return new PageImpl(result, pageable, count);
|
||||
}
|
||||
@@ -206,8 +198,8 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
|
||||
@Override
|
||||
Object execute(Query query) {
|
||||
|
||||
MongoEntityInformation<?, ?> entityInformation = method.getEntityInformation();
|
||||
return operations.findOne(query, entityInformation.getJavaType());
|
||||
MongoEntityMetadata<?> metadata = method.getEntityInformation();
|
||||
return operations.findOne(query, metadata.getJavaType());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -244,8 +236,8 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
|
||||
*/
|
||||
Object execute(Query query, Query countQuery) {
|
||||
|
||||
MongoEntityInformation<?, ?> information = method.getEntityInformation();
|
||||
long count = operations.count(countQuery, information.getCollectionName());
|
||||
MongoEntityMetadata<?> metadata = method.getEntityInformation();
|
||||
long count = operations.count(countQuery, metadata.getCollectionName());
|
||||
|
||||
return new GeoPage<Object>(doExecuteQuery(query), accessor.getPageable(), count);
|
||||
}
|
||||
@@ -265,9 +257,8 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
|
||||
nearQuery.maxDistance(maxDistance);
|
||||
}
|
||||
|
||||
MongoEntityInformation<?, ?> entityInformation = method.getEntityInformation();
|
||||
return (GeoResults<Object>) operations.geoNear(nearQuery, entityInformation.getJavaType(),
|
||||
entityInformation.getCollectionName());
|
||||
MongoEntityMetadata<?> metadata = method.getEntityInformation();
|
||||
return (GeoResults<Object>) operations.geoNear(nearQuery, metadata.getJavaType(), metadata.getCollectionName());
|
||||
}
|
||||
|
||||
private boolean isListOfGeoResult() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
* Copyright 2011-2013 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.
|
||||
@@ -15,7 +15,11 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.repository.query;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
@@ -24,7 +28,11 @@ import org.springframework.data.mongodb.core.geo.Distance;
|
||||
import org.springframework.data.mongodb.core.geo.Point;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
import org.springframework.data.repository.query.ParameterAccessor;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import com.mongodb.DBRef;
|
||||
|
||||
/**
|
||||
* Custom {@link ParameterAccessor} that uses a {@link MongoWriter} to serialize parameters into Mongo format.
|
||||
@@ -78,12 +86,12 @@ public class ConvertingParameterAccessor implements MongoParameterAccessor {
|
||||
return delegate.getSort();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.query.ParameterAccessor#getBindableParameter(int)
|
||||
*/
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.query.ParameterAccessor#getBindableValue(int)
|
||||
*/
|
||||
public Object getBindableValue(int index) {
|
||||
|
||||
return getConvertedValue(delegate.getBindableValue(index));
|
||||
return getConvertedValue(delegate.getBindableValue(index), null);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -94,7 +102,8 @@ public class ConvertingParameterAccessor implements MongoParameterAccessor {
|
||||
return delegate.getMaxDistance();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.repository.MongoParameterAccessor#getGeoNearLocation()
|
||||
*/
|
||||
public Point getGeoNearLocation() {
|
||||
@@ -104,11 +113,12 @@ public class ConvertingParameterAccessor implements MongoParameterAccessor {
|
||||
/**
|
||||
* Converts the given value with the underlying {@link MongoWriter}.
|
||||
*
|
||||
* @param value
|
||||
* @param value can be {@literal null}.
|
||||
* @param typeInformation can be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
private Object getConvertedValue(Object value) {
|
||||
return writer.convertToMongoType(value);
|
||||
private Object getConvertedValue(Object value, TypeInformation<?> typeInformation) {
|
||||
return writer.convertToMongoType(value, typeInformation == null ? null : typeInformation.getActualType());
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -158,7 +168,28 @@ public class ConvertingParameterAccessor implements MongoParameterAccessor {
|
||||
* @see org.springframework.data.mongodb.repository.ConvertingParameterAccessor.PotentiallConvertingIterator#nextConverted()
|
||||
*/
|
||||
public Object nextConverted(MongoPersistentProperty property) {
|
||||
return property.isAssociation() ? writer.toDBRef(next(), property) : getConvertedValue(next());
|
||||
|
||||
Object next = next();
|
||||
|
||||
if (next == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (property.isAssociation()) {
|
||||
if (next.getClass().isArray() || next instanceof Iterable) {
|
||||
|
||||
List<DBRef> dbRefs = new ArrayList<DBRef>();
|
||||
for (Object element : asCollection(next)) {
|
||||
dbRefs.add(writer.toDBRef(element, property));
|
||||
}
|
||||
|
||||
return dbRefs;
|
||||
} else {
|
||||
return writer.toDBRef(next, property);
|
||||
}
|
||||
}
|
||||
|
||||
return getConvertedValue(next, property.getTypeInformation());
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -170,6 +201,33 @@ public class ConvertingParameterAccessor implements MongoParameterAccessor {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the given object as {@link Collection}. Will do a copy of it if it implements {@link Iterable} or is an
|
||||
* array. Will return an empty {@link Collection} in case {@literal null} is given. Will wrap all other types into a
|
||||
* single-element collction
|
||||
*
|
||||
* @param source
|
||||
* @return
|
||||
*/
|
||||
private static Collection<?> asCollection(Object source) {
|
||||
|
||||
if (source instanceof Iterable) {
|
||||
|
||||
List<Object> result = new ArrayList<Object>();
|
||||
for (Object element : (Iterable<?>) source) {
|
||||
result.add(element);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (source == null) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
return source.getClass().isArray() ? CollectionUtils.arrayToList(source) : Collections.singleton(source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom {@link Iterator} that adds a method to access elements in a converted manner.
|
||||
*
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 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.query;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Interface for components being able to provide {@link EntityInformationCreator} for a given {@link Class}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface EntityInformationCreator {
|
||||
|
||||
/**
|
||||
* Returns a {@link MongoEntityInformation} for the given domain class.
|
||||
*
|
||||
* @param domainClass the domain class to create the {@link MongoEntityInformation} for, must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
<T, ID extends Serializable> MongoEntityInformation<T, ID> getEntityInformation(Class<T> domainClass);
|
||||
|
||||
/**
|
||||
* Returns a {@link MongoEntityInformation} for the given domain class and class to retrieve the collection to query
|
||||
* against from.
|
||||
*
|
||||
* @param domainClass the domain class to create the {@link MongoEntityInformation} for, must not be {@literal null}.
|
||||
* @param collectionClass the class to derive the collection from queries to retrieve the domain classes from shall be
|
||||
* ran against, must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
<T, ID extends Serializable> MongoEntityInformation<T, ID> getEntityInformation(Class<T> domainClass,
|
||||
Class<?> collectionClass);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2012 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.query;
|
||||
|
||||
import org.springframework.data.repository.core.EntityMetadata;
|
||||
|
||||
/**
|
||||
* Extension of {@link EntityMetadata} to additionally expose the collection name an entity shall be persisted to.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface MongoEntityMetadata<T> extends EntityMetadata<T> {
|
||||
|
||||
/**
|
||||
* Returns the name of the collection the entity shall be persisted to.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String getCollectionName();
|
||||
}
|
||||
@@ -147,8 +147,7 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
|
||||
return null;
|
||||
}
|
||||
|
||||
Query query = new Query(criteria);
|
||||
QueryUtils.applySorting(query, sort);
|
||||
Query query = new Query(criteria).with(sort);
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Created query " + query);
|
||||
@@ -228,7 +227,7 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
|
||||
case SIMPLE_PROPERTY:
|
||||
return criteria.is(parameters.nextConverted(property));
|
||||
case NEGATING_SIMPLE_PROPERTY:
|
||||
return criteria.not().is(parameters.nextConverted(property));
|
||||
return criteria.ne(parameters.nextConverted(property));
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Unsupported keyword!");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
* Copyright 2011-2012 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.
|
||||
@@ -20,9 +20,12 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mongodb.core.geo.GeoPage;
|
||||
import org.springframework.data.mongodb.core.geo.GeoResult;
|
||||
import org.springframework.data.mongodb.core.geo.GeoResults;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
import org.springframework.data.mongodb.repository.Query;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.query.Parameters;
|
||||
@@ -33,8 +36,7 @@ import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* TODO - Extract methods for {@link #getAnnotatedQuery()} into superclass as it is currently copied from Spring Data
|
||||
* JPA
|
||||
* Mongo specific implementation of {@link QueryMethod}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@@ -45,19 +47,24 @@ public class MongoQueryMethod extends QueryMethod {
|
||||
.asList(GeoResult.class, GeoResults.class, GeoPage.class);
|
||||
|
||||
private final Method method;
|
||||
private final MongoEntityInformation<?, ?> entityInformation;
|
||||
private final MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
|
||||
|
||||
private MongoEntityMetadata<?> metadata;
|
||||
|
||||
/**
|
||||
* Creates a new {@link MongoQueryMethod} from the given {@link Method}.
|
||||
*
|
||||
* @param method
|
||||
*/
|
||||
public MongoQueryMethod(Method method, RepositoryMetadata metadata, EntityInformationCreator entityInformationCreator) {
|
||||
public MongoQueryMethod(Method method, RepositoryMetadata metadata,
|
||||
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext) {
|
||||
|
||||
super(method, metadata);
|
||||
Assert.notNull(entityInformationCreator, "DefaultEntityInformationCreator must not be null!");
|
||||
|
||||
Assert.notNull(mappingContext, "MappingContext must not be null!");
|
||||
|
||||
this.method = method;
|
||||
this.entityInformation = entityInformationCreator.getEntityInformation(metadata.getReturnedDomainClass(method),
|
||||
getDomainClass());
|
||||
this.mappingContext = mappingContext;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -101,14 +108,30 @@ public class MongoQueryMethod extends QueryMethod {
|
||||
return StringUtils.hasText(value) ? value : null;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.query.QueryMethod#getEntityInformation()
|
||||
*/
|
||||
@Override
|
||||
public MongoEntityInformation<?, ?> getEntityInformation() {
|
||||
@SuppressWarnings("unchecked")
|
||||
public MongoEntityMetadata<?> getEntityInformation() {
|
||||
|
||||
return entityInformation;
|
||||
if (metadata == null) {
|
||||
|
||||
Class<?> returnedObjectType = getReturnedObjectType();
|
||||
Class<?> domainClass = getDomainClass();
|
||||
|
||||
MongoPersistentEntity<?> returnedEntity = mappingContext.getPersistentEntity(getReturnedObjectType());
|
||||
MongoPersistentEntity<?> managedEntity = mappingContext.getPersistentEntity(domainClass);
|
||||
returnedEntity = returnedEntity == null ? managedEntity : returnedEntity;
|
||||
MongoPersistentEntity<?> collectionEntity = domainClass.isAssignableFrom(returnedObjectType) ? returnedEntity
|
||||
: managedEntity;
|
||||
|
||||
this.metadata = new SimpleMongoEntityMetadata<Object>((Class<Object>) returnedEntity.getType(),
|
||||
collectionEntity.getCollection());
|
||||
}
|
||||
|
||||
return this.metadata;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -121,12 +144,11 @@ public class MongoQueryMethod extends QueryMethod {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether te query is a geoNear query.
|
||||
* Returns whether te query is a geo near query.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isGeoNearQuery() {
|
||||
|
||||
return isGeoNearQuery(this.method);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2011 the original author or authors.
|
||||
* Copyright 2010-2012 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.
|
||||
@@ -15,12 +15,13 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.repository.query;
|
||||
|
||||
import com.mongodb.DBCursor;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.domain.Sort.Order;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
|
||||
import com.mongodb.DBCursor;
|
||||
|
||||
/**
|
||||
* Collection of utility methods to apply sorting and pagination to a {@link DBCursor}.
|
||||
*
|
||||
@@ -36,10 +37,12 @@ public abstract class QueryUtils {
|
||||
* Applies the given {@link Pageable} to the given {@link Query}. Will do nothing if {@link Pageable} is
|
||||
* {@literal null}.
|
||||
*
|
||||
* @param query
|
||||
* @deprecated use {@link Query#with(Pageable)}.
|
||||
* @param query must not be {@literal null}.
|
||||
* @param pageable
|
||||
* @return
|
||||
*/
|
||||
@Deprecated
|
||||
public static Query applyPagination(Query query, Pageable pageable) {
|
||||
|
||||
if (pageable == null) {
|
||||
@@ -49,16 +52,18 @@ public abstract class QueryUtils {
|
||||
query.limit(pageable.getPageSize());
|
||||
query.skip(pageable.getOffset());
|
||||
|
||||
return applySorting(query, pageable.getSort());
|
||||
return query.with(pageable.getSort());
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the given {@link Sort} to the {@link Query}. Will do nothing if {@link Sort} is {@literal null}.
|
||||
*
|
||||
* @param query
|
||||
* @deprecated use {@link Query#with(Pageable)}.
|
||||
* @param query must not be {@literal null}.
|
||||
* @param sort
|
||||
* @return
|
||||
*/
|
||||
@Deprecated
|
||||
public static Query applySorting(Query query, Sort sort) {
|
||||
|
||||
if (sort == null) {
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2012 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.query;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Bean based implementation of {@link MongoEntityMetadata}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
class SimpleMongoEntityMetadata<T> implements MongoEntityMetadata<T> {
|
||||
|
||||
private final Class<T> type;
|
||||
private final String collectionName;
|
||||
|
||||
/**
|
||||
* Creates a new {@link SimpleMongoEntityMetadata} using the given type and collection name.
|
||||
*
|
||||
* @param type must not be {@literal null}.
|
||||
* @param collectionName must not be {@literal null} or empty.
|
||||
*/
|
||||
public SimpleMongoEntityMetadata(Class<T> type, String collectionName) {
|
||||
|
||||
Assert.notNull(type, "Type must not be null!");
|
||||
Assert.hasText(collectionName, "Collection name must not be null or empty!");
|
||||
|
||||
this.type = type;
|
||||
this.collectionName = collectionName;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.core.EntityMetadata#getJavaType()
|
||||
*/
|
||||
public Class<T> getJavaType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.repository.query.MongoEntityMetadata#getCollectionName()
|
||||
*/
|
||||
public String getCollectionName() {
|
||||
return collectionName;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
* Copyright 2011-2012 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.
|
||||
@@ -73,7 +73,7 @@ public class StringBasedMongoQuery extends AbstractMongoQuery {
|
||||
query = new BasicQuery(queryString);
|
||||
}
|
||||
|
||||
QueryUtils.applySorting(query, accessor.getSort());
|
||||
query.with(accessor.getSort());
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug(String.format("Created query %s", query.getQueryObject()));
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 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.support;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
import org.springframework.data.mongodb.repository.query.EntityInformationCreator;
|
||||
import org.springframework.data.mongodb.repository.query.MongoEntityInformation;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Simple {@link EntityInformationCreator} to to create {@link MongoEntityInformation} instances based on a
|
||||
* {@link MappingContext}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class DefaultEntityInformationCreator implements EntityInformationCreator {
|
||||
|
||||
private final MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
|
||||
|
||||
public DefaultEntityInformationCreator(
|
||||
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext) {
|
||||
Assert.notNull(mappingContext);
|
||||
this.mappingContext = mappingContext;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.repository.support.EntityInformationCreator#getEntityInformation(java.lang.Class)
|
||||
*/
|
||||
public <T, ID extends Serializable> MongoEntityInformation<T, ID> getEntityInformation(Class<T> domainClass) {
|
||||
return getEntityInformation(domainClass, null);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.repository.support.EntityInformationCreator#getEntityInformation(java.lang.Class, java.lang.Class)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T, ID extends Serializable> MongoEntityInformation<T, ID> getEntityInformation(Class<T> domainClass,
|
||||
Class<?> collectionClass) {
|
||||
|
||||
MongoPersistentEntity<T> persistentEntity = (MongoPersistentEntity<T>) mappingContext
|
||||
.getPersistentEntity(domainClass);
|
||||
String customCollectionName = collectionClass == null ? null : mappingContext.getPersistentEntity(collectionClass)
|
||||
.getCollection();
|
||||
|
||||
return new MappingMongoEntityInformation<T, ID>(persistentEntity, customCollectionName);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
* Copyright 2011-2012 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.
|
||||
@@ -25,7 +25,7 @@ import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.mongodb.core.MongoOperations;
|
||||
import org.springframework.data.mongodb.core.index.Index;
|
||||
import org.springframework.data.mongodb.core.query.Order;
|
||||
import org.springframework.data.mongodb.repository.query.MongoEntityInformation;
|
||||
import org.springframework.data.mongodb.repository.query.MongoEntityMetadata;
|
||||
import org.springframework.data.mongodb.repository.query.PartTreeMongoQuery;
|
||||
import org.springframework.data.mongodb.repository.query.QueryUtils;
|
||||
import org.springframework.data.repository.core.support.QueryCreationListener;
|
||||
@@ -85,7 +85,7 @@ class IndexEnsuringQueryCreationListener implements QueryCreationListener<PartTr
|
||||
}
|
||||
}
|
||||
|
||||
MongoEntityInformation<?, ?> metadata = query.getQueryMethod().getEntityInformation();
|
||||
MongoEntityMetadata<?> metadata = query.getQueryMethod().getEntityInformation();
|
||||
operations.indexOps(metadata.getCollectionName()).ensureIndex(index);
|
||||
LOG.debug(String.format("Created %s!", index));
|
||||
}
|
||||
@@ -99,4 +99,4 @@ class IndexEnsuringQueryCreationListener implements QueryCreationListener<PartTr
|
||||
org.springframework.data.domain.Sort.Order order = sort.getOrderFor(property);
|
||||
return order == null ? Order.DESCENDING : order.isAscending() ? Order.ASCENDING : Order.DESCENDING;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2011 the original author or authors.
|
||||
* Copyright 2010-2012 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.
|
||||
@@ -21,10 +21,11 @@ import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.mongodb.core.MongoOperations;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
import org.springframework.data.mongodb.repository.MongoRepository;
|
||||
import org.springframework.data.mongodb.repository.query.EntityInformationCreator;
|
||||
import org.springframework.data.mongodb.repository.query.MongoEntityInformation;
|
||||
import org.springframework.data.mongodb.repository.query.MongoQueryMethod;
|
||||
import org.springframework.data.mongodb.repository.query.PartTreeMongoQuery;
|
||||
@@ -46,20 +47,18 @@ import org.springframework.util.Assert;
|
||||
public class MongoRepositoryFactory extends RepositoryFactorySupport {
|
||||
|
||||
private final MongoOperations mongoOperations;
|
||||
private final EntityInformationCreator entityInformationCreator;
|
||||
private final MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
|
||||
|
||||
/**
|
||||
* Creates a new {@link MongoRepositoryFactory} with the given {@link MongoTemplate} and {@link MappingContext}.
|
||||
* Creates a new {@link MongoRepositoryFactory} with the given {@link MongoOperations}.
|
||||
*
|
||||
* @param template must not be {@literal null}
|
||||
* @param mappingContext
|
||||
* @param mongoOperations must not be {@literal null}
|
||||
*/
|
||||
public MongoRepositoryFactory(MongoOperations mongoOperations) {
|
||||
|
||||
Assert.notNull(mongoOperations);
|
||||
this.mongoOperations = mongoOperations;
|
||||
this.entityInformationCreator = new DefaultEntityInformationCreator(mongoOperations.getConverter()
|
||||
.getMappingContext());
|
||||
this.mappingContext = mongoOperations.getConverter().getMappingContext();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -117,7 +116,7 @@ public class MongoRepositoryFactory extends RepositoryFactorySupport {
|
||||
*/
|
||||
public RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, NamedQueries namedQueries) {
|
||||
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, entityInformationCreator);
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, mappingContext);
|
||||
String namedQueryName = queryMethod.getNamedQueryName();
|
||||
|
||||
if (namedQueries.hasQuery(namedQueryName)) {
|
||||
@@ -136,7 +135,16 @@ public class MongoRepositoryFactory extends RepositoryFactorySupport {
|
||||
* @see org.springframework.data.repository.core.support.RepositoryFactorySupport#getEntityInformation(java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T, ID extends Serializable> MongoEntityInformation<T, ID> getEntityInformation(Class<T> domainClass) {
|
||||
return entityInformationCreator.getEntityInformation(domainClass);
|
||||
|
||||
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(domainClass);
|
||||
|
||||
if (entity == null) {
|
||||
throw new MappingException(String.format("Could not lookup mapping metadata for domain class %s!",
|
||||
domainClass.getName()));
|
||||
}
|
||||
|
||||
return new MappingMongoEntityInformation<T, ID>((MongoPersistentEntity<T>) entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2011 the original author or authors.
|
||||
* Copyright 2010-2012 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.
|
||||
@@ -34,7 +34,6 @@ import org.springframework.data.mongodb.core.query.Criteria;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.data.mongodb.repository.MongoRepository;
|
||||
import org.springframework.data.mongodb.repository.query.MongoEntityInformation;
|
||||
import org.springframework.data.mongodb.repository.query.QueryUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -115,8 +114,11 @@ public class SimpleMongoRepository<T, ID extends Serializable> implements MongoR
|
||||
public boolean exists(ID id) {
|
||||
|
||||
Assert.notNull(id, "The given id must not be null!");
|
||||
return mongoOperations.findOne(new Query(Criteria.where("_id").is(id)), Object.class,
|
||||
entityInformation.getCollectionName()) != null;
|
||||
|
||||
final Query idQuery = getIdQuery(id);
|
||||
idQuery.fields();
|
||||
|
||||
return mongoOperations.findOne(idQuery, entityInformation.getJavaType(), entityInformation.getCollectionName()) != null;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -197,7 +199,7 @@ public class SimpleMongoRepository<T, ID extends Serializable> implements MongoR
|
||||
public Page<T> findAll(final Pageable pageable) {
|
||||
|
||||
Long count = count();
|
||||
List<T> list = findAll(QueryUtils.applyPagination(new Query(), pageable));
|
||||
List<T> list = findAll(new Query().with(pageable));
|
||||
|
||||
return new PageImpl<T>(list, pageable, count);
|
||||
}
|
||||
@@ -206,9 +208,8 @@ public class SimpleMongoRepository<T, ID extends Serializable> implements MongoR
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.PagingAndSortingRepository#findAll(org.springframework.data.domain.Sort)
|
||||
*/
|
||||
public List<T> findAll(final Sort sort) {
|
||||
|
||||
return findAll(QueryUtils.applySorting(new Query(), sort));
|
||||
public List<T> findAll(Sort sort) {
|
||||
return findAll(new Query().with(sort));
|
||||
}
|
||||
|
||||
private List<T> findAll(Query query) {
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<xsd:import namespace="http://www.springframework.org/schema/context"
|
||||
schemaLocation="http://www.springframework.org/schema/context/spring-context.xsd" />
|
||||
<xsd:import namespace="http://www.springframework.org/schema/data/repository"
|
||||
schemaLocation="http://www.springframework.org/schema/data/repository/spring-repository.xsd" />
|
||||
schemaLocation="http://www.springframework.org/schema/data/repository/spring-repository-1.0.xsd" />
|
||||
|
||||
<xsd:element name="mongo" type="mongoType">
|
||||
<xsd:annotation>
|
||||
@@ -44,8 +44,9 @@ The name of the mongo definition (by default "mongoDbFactory").]]></xsd:document
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="mongo-ref" type="mongoRef" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
The reference to a Mongo. Will default to 'mongo'.
|
||||
<xsd:documentation><![CDATA[
|
||||
The reference to a Mongo instance. If not configured a default com.mongodb.Mongo instance will be created.
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
|
||||
@@ -44,8 +44,9 @@ The name of the mongo definition (by default "mongoDbFactory").]]></xsd:document
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="mongo-ref" type="mongoRef" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
The reference to a Mongo. Will default to 'mongo'.
|
||||
<xsd:documentation><![CDATA[
|
||||
The reference to a Mongo instance. If not configured a default com.mongodb.Mongo instance will be created.
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright 2012 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.config;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
|
||||
import com.mongodb.Mongo;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link AbstractMongoConfiguration}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class AbstractMongoConfigurationUnitTests {
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-496
|
||||
*/
|
||||
@Test
|
||||
public void usesConfigClassPackageAsBaseMappingPackage() throws ClassNotFoundException {
|
||||
|
||||
AbstractMongoConfiguration configuration = new SampleMongoConfiguration();
|
||||
assertThat(configuration.getMappingBasePackage(), is(SampleMongoConfiguration.class.getPackage().getName()));
|
||||
assertThat(configuration.getInitialEntitySet(), hasSize(1));
|
||||
assertThat(configuration.getInitialEntitySet(), hasItem(Entity.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-496
|
||||
*/
|
||||
@Test
|
||||
public void doesNotScanPackageIfMappingPackageIsNull() throws ClassNotFoundException {
|
||||
|
||||
assertScanningDisabled(null);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-496
|
||||
*/
|
||||
@Test
|
||||
public void doesNotScanPackageIfMappingPackageIsEmpty() throws ClassNotFoundException {
|
||||
|
||||
assertScanningDisabled("");
|
||||
assertScanningDisabled(" ");
|
||||
}
|
||||
|
||||
private static void assertScanningDisabled(final String value) throws ClassNotFoundException {
|
||||
|
||||
AbstractMongoConfiguration configuration = new SampleMongoConfiguration() {
|
||||
@Override
|
||||
protected String getMappingBasePackage() {
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
assertThat(configuration.getMappingBasePackage(), is(value));
|
||||
assertThat(configuration.getInitialEntitySet(), hasSize(0));
|
||||
}
|
||||
|
||||
static class SampleMongoConfiguration extends AbstractMongoConfiguration {
|
||||
|
||||
@Override
|
||||
protected String getDatabaseName() {
|
||||
return "database";
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Override
|
||||
public Mongo mongo() throws Exception {
|
||||
return new Mongo();
|
||||
}
|
||||
}
|
||||
|
||||
@Document
|
||||
static class Entity {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright 2012 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.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import com.mongodb.BasicDBList;
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* Helper classes to ease assertions on {@link DBObject}s.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public abstract class DBObjectUtils {
|
||||
|
||||
private DBObjectUtils() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Expects the field with the given key to be not {@literal null} and a {@link DBObject} in turn and returns it.
|
||||
*
|
||||
* @param source the {@link DBObject} to lookup the nested one
|
||||
* @param key the key of the field to lokup the nested {@link DBObject}
|
||||
* @return
|
||||
*/
|
||||
public static DBObject getAsDBObject(DBObject source, String key) {
|
||||
return getTypedValue(source, key, DBObject.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Expects the field with the given key to be not {@literal null} and a {@link BasicDBList}.
|
||||
*
|
||||
* @param source the {@link DBObject} to lookup the {@link BasicDBList} in
|
||||
* @param key the key of the field to find the {@link BasicDBList} in
|
||||
* @return
|
||||
*/
|
||||
public static BasicDBList getAsDBList(DBObject source, String key) {
|
||||
return getTypedValue(source, key, BasicDBList.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Expects the list element with the given index to be a non-{@literal null} {@link DBObject} and returns it.
|
||||
*
|
||||
* @param source the {@link BasicDBList} to look up the {@link DBObject} element in
|
||||
* @param index the index of the element expected to contain a {@link DBObject}
|
||||
* @return
|
||||
*/
|
||||
public static DBObject getAsDBObject(BasicDBList source, int index) {
|
||||
|
||||
assertThat(source.size(), greaterThanOrEqualTo(index + 1));
|
||||
Object value = source.get(index);
|
||||
assertThat(value, is(instanceOf(DBObject.class)));
|
||||
return (DBObject) value;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <T> T getTypedValue(DBObject source, String key, Class<T> type) {
|
||||
|
||||
Object value = source.get(key);
|
||||
assertThat(value, is(notNullValue()));
|
||||
assertThat(value, is(instanceOf(type)));
|
||||
|
||||
return (T) value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright 2012 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 java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.authentication.UserCredentials;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolExecutorFactoryBean;
|
||||
|
||||
import com.mongodb.DB;
|
||||
import com.mongodb.Mongo;
|
||||
import com.mongodb.MongoException;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link MongoDbUtils}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class MongoDbUtilsIntegrationTests {
|
||||
|
||||
static final String DATABASE_NAME = "dbAuthTests";
|
||||
static final UserCredentials CREDENTIALS = new UserCredentials("admin", "admin");
|
||||
|
||||
static Mongo mongo;
|
||||
static MongoTemplate template;
|
||||
static ThreadPoolExecutorFactoryBean factory;
|
||||
static ExecutorService service;
|
||||
|
||||
Exception exception;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUp() throws Exception {
|
||||
|
||||
mongo = new Mongo();
|
||||
template = new MongoTemplate(mongo, DATABASE_NAME);
|
||||
|
||||
// Create sample user
|
||||
template.execute(new DbCallback<Void>() {
|
||||
public Void doInDB(DB db) throws MongoException, DataAccessException {
|
||||
db.addUser("admin", "admin".toCharArray());
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
factory = new ThreadPoolExecutorFactoryBean();
|
||||
factory.setCorePoolSize(2);
|
||||
factory.setMaxPoolSize(10);
|
||||
factory.setWaitForTasksToCompleteOnShutdown(true);
|
||||
factory.afterPropertiesSet();
|
||||
|
||||
service = factory.getObject();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDown() {
|
||||
|
||||
factory.destroy();
|
||||
|
||||
// Remove test database
|
||||
|
||||
template.execute(new DbCallback<Void>() {
|
||||
public Void doInDB(DB db) throws MongoException, DataAccessException {
|
||||
db.dropDatabase();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-585
|
||||
*/
|
||||
@Test
|
||||
public void authenticatesCorrectlyInMultithreadedEnvironment() throws Exception {
|
||||
|
||||
Callable<Void> callable = new Callable<Void>() {
|
||||
public Void call() throws Exception {
|
||||
|
||||
try {
|
||||
DB db = MongoDbUtils.getDB(mongo, DATABASE_NAME, CREDENTIALS);
|
||||
assertThat(db, is(notNullValue()));
|
||||
} catch (Exception o_O) {
|
||||
MongoDbUtilsIntegrationTests.this.exception = o_O;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
List<Callable<Void>> callables = new ArrayList<Callable<Void>>();
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
callables.add(callable);
|
||||
}
|
||||
|
||||
service.invokeAll(callables);
|
||||
|
||||
if (exception != null) {
|
||||
fail("Exception occurred!" + exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,10 +17,17 @@ package org.springframework.data.mongodb.core;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Matchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.mockito.stubbing.Answer;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
|
||||
import com.mongodb.DB;
|
||||
@@ -31,13 +38,21 @@ import com.mongodb.Mongo;
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class MongoDbUtilsUnitTests {
|
||||
|
||||
@Mock
|
||||
Mongo mongo;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
this.mongo = new Mongo();
|
||||
|
||||
when(mongo.getDB(anyString())).then(new Answer<DB>() {
|
||||
public DB answer(InvocationOnMock invocation) throws Throwable {
|
||||
return mock(DB.class);
|
||||
}
|
||||
});
|
||||
|
||||
TransactionSynchronizationManager.initSynchronization();
|
||||
}
|
||||
|
||||
@@ -55,11 +70,15 @@ public class MongoDbUtilsUnitTests {
|
||||
public void returnsNewInstanceForDifferentDatabaseName() {
|
||||
|
||||
DB first = MongoDbUtils.getDB(mongo, "first");
|
||||
assertThat(first, is(notNullValue()));
|
||||
assertThat(MongoDbUtils.getDB(mongo, "first"), is(first));
|
||||
|
||||
DB second = MongoDbUtils.getDB(mongo, "second");
|
||||
assertThat(second, is(not(first)));
|
||||
assertThat(MongoDbUtils.getDB(mongo, "second"), is(second));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void returnsSameInstanceForSameDatabaseName() {
|
||||
|
||||
DB first = MongoDbUtils.getDB(mongo, "first");
|
||||
assertThat(first, is(notNullValue()));
|
||||
assertThat(MongoDbUtils.getDB(mongo, "first"), is(sameInstance(first)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright 2013 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 java.io.IOException;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.NestedRuntimeException;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.dao.InvalidDataAccessResourceUsageException;
|
||||
import org.springframework.data.mongodb.UncategorizedMongoDbException;
|
||||
|
||||
import com.mongodb.MongoException;
|
||||
import com.mongodb.MongoException.DuplicateKey;
|
||||
import com.mongodb.MongoException.Network;
|
||||
import com.mongodb.MongoInternalException;
|
||||
import com.mongodb.ServerAddress;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link MongoExceptionTranslator}.
|
||||
*
|
||||
* @author Michal Vich
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class MongoExceptionTranslatorUnitTests {
|
||||
|
||||
MongoExceptionTranslator translator;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
translator = new MongoExceptionTranslator();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void translateDuplicateKey() {
|
||||
|
||||
DuplicateKey exception = new DuplicateKey(1, "Duplicated key");
|
||||
DataAccessException translatedException = translator.translateExceptionIfPossible(exception);
|
||||
|
||||
expectExceptionWithCauseMessage(translatedException, DuplicateKeyException.class, "Duplicated key");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void translateNetwork() {
|
||||
|
||||
Network exception = new Network("IOException", new IOException("IOException"));
|
||||
DataAccessException translatedException = translator.translateExceptionIfPossible(exception);
|
||||
|
||||
expectExceptionWithCauseMessage(translatedException, DataAccessResourceFailureException.class, "IOException");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void translateCursorNotFound() throws UnknownHostException {
|
||||
|
||||
MongoException.CursorNotFound exception = new MongoException.CursorNotFound(1, new ServerAddress());
|
||||
DataAccessException translatedException = translator.translateExceptionIfPossible(exception);
|
||||
|
||||
expectExceptionWithCauseMessage(translatedException, DataAccessResourceFailureException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void translateToDuplicateKeyException() {
|
||||
|
||||
checkTranslatedMongoException(DuplicateKeyException.class, 11000);
|
||||
checkTranslatedMongoException(DuplicateKeyException.class, 11001);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void translateToDataAccessResourceFailureException() {
|
||||
|
||||
checkTranslatedMongoException(DataAccessResourceFailureException.class, 12000);
|
||||
checkTranslatedMongoException(DataAccessResourceFailureException.class, 13440);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void translateToInvalidDataAccessApiUsageException() {
|
||||
|
||||
checkTranslatedMongoException(InvalidDataAccessApiUsageException.class, 10003);
|
||||
checkTranslatedMongoException(InvalidDataAccessApiUsageException.class, 12001);
|
||||
checkTranslatedMongoException(InvalidDataAccessApiUsageException.class, 12010);
|
||||
checkTranslatedMongoException(InvalidDataAccessApiUsageException.class, 12011);
|
||||
checkTranslatedMongoException(InvalidDataAccessApiUsageException.class, 12012);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void translateToUncategorizedMongoDbException() {
|
||||
|
||||
MongoException exception = new MongoException(0, "");
|
||||
DataAccessException translatedException = translator.translateExceptionIfPossible(exception);
|
||||
|
||||
expectExceptionWithCauseMessage(translatedException, UncategorizedMongoDbException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void translateMongoInternalException() {
|
||||
|
||||
MongoInternalException exception = new MongoInternalException("Internal exception");
|
||||
DataAccessException translatedException = translator.translateExceptionIfPossible(exception);
|
||||
|
||||
expectExceptionWithCauseMessage(translatedException, InvalidDataAccessResourceUsageException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void translateUnsupportedException() {
|
||||
|
||||
RuntimeException exception = new RuntimeException();
|
||||
assertThat(translator.translateExceptionIfPossible(exception), is(nullValue()));
|
||||
}
|
||||
|
||||
private void checkTranslatedMongoException(Class<? extends Exception> clazz, int code) {
|
||||
|
||||
try {
|
||||
translator.translateExceptionIfPossible(new MongoException(code, ""));
|
||||
fail("Expected exception of type " + clazz.getName() + "!");
|
||||
} catch (NestedRuntimeException e) {
|
||||
Throwable cause = e.getRootCause();
|
||||
assertThat(cause, is(instanceOf(MongoException.class)));
|
||||
assertThat(((MongoException) cause).getCode(), is(code));
|
||||
}
|
||||
}
|
||||
|
||||
private static void expectExceptionWithCauseMessage(NestedRuntimeException e,
|
||||
Class<? extends NestedRuntimeException> type) {
|
||||
expectExceptionWithCauseMessage(e, type, null);
|
||||
}
|
||||
|
||||
private static void expectExceptionWithCauseMessage(NestedRuntimeException e,
|
||||
Class<? extends NestedRuntimeException> type, String message) {
|
||||
|
||||
assertThat(e, is(instanceOf(type)));
|
||||
|
||||
if (message != null) {
|
||||
assertThat(e.getRootCause(), is(notNullValue()));
|
||||
assertThat(e.getRootCause().getMessage(), containsString(message));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
* Copyright 2011-2013 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.
|
||||
@@ -34,6 +34,7 @@ import org.springframework.data.mongodb.core.geo.Point;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
import org.springframework.data.mongodb.core.query.NearQuery;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DBObject;
|
||||
@@ -78,7 +79,7 @@ public abstract class MongoOperationsUnitTests {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object convertToMongoType(Object obj) {
|
||||
public Object convertToMongoType(Object obj, TypeInformation<?> typeInformation) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,8 +24,10 @@ import static org.springframework.data.mongodb.core.query.Update.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.bson.types.ObjectId;
|
||||
import org.joda.time.DateTime;
|
||||
@@ -40,8 +42,11 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.dao.OptimisticLockingFailureException;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.annotation.PersistenceConstructor;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.mongodb.InvalidMongoDbApiUsageException;
|
||||
import org.springframework.data.mongodb.MongoDbFactory;
|
||||
import org.springframework.data.mongodb.core.convert.CustomConversions;
|
||||
@@ -51,6 +56,7 @@ import org.springframework.data.mongodb.core.index.Index.Duplicates;
|
||||
import org.springframework.data.mongodb.core.index.IndexField;
|
||||
import org.springframework.data.mongodb.core.index.IndexInfo;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||
import org.springframework.data.mongodb.core.query.BasicQuery;
|
||||
import org.springframework.data.mongodb.core.query.Criteria;
|
||||
import org.springframework.data.mongodb.core.query.Order;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
@@ -58,6 +64,7 @@ import org.springframework.data.mongodb.core.query.Update;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DBCollection;
|
||||
import com.mongodb.DBCursor;
|
||||
import com.mongodb.DBObject;
|
||||
@@ -74,6 +81,7 @@ import com.mongodb.WriteResult;
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Risberg
|
||||
* @author Amol Nayak
|
||||
* @author Patryk Wasik
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration("classpath:infrastructure.xml")
|
||||
@@ -123,18 +131,21 @@ public class MongoTemplateTests {
|
||||
}
|
||||
|
||||
protected void cleanDb() {
|
||||
template.dropCollection(template.getCollectionName(Person.class));
|
||||
template.dropCollection(template.getCollectionName(PersonWithAList.class));
|
||||
template.dropCollection(template.getCollectionName(PersonWith_idPropertyOfTypeObjectId.class));
|
||||
template.dropCollection(template.getCollectionName(PersonWith_idPropertyOfTypeString.class));
|
||||
template.dropCollection(template.getCollectionName(PersonWithIdPropertyOfTypeObjectId.class));
|
||||
template.dropCollection(template.getCollectionName(PersonWithIdPropertyOfTypeString.class));
|
||||
template.dropCollection(template.getCollectionName(PersonWithIdPropertyOfTypeInteger.class));
|
||||
template.dropCollection(template.getCollectionName(PersonWithIdPropertyOfPrimitiveInt.class));
|
||||
template.dropCollection(template.getCollectionName(PersonWithIdPropertyOfTypeLong.class));
|
||||
template.dropCollection(template.getCollectionName(PersonWithIdPropertyOfPrimitiveLong.class));
|
||||
template.dropCollection(template.getCollectionName(TestClass.class));
|
||||
template.dropCollection(Person.class);
|
||||
template.dropCollection(PersonWithAList.class);
|
||||
template.dropCollection(PersonWith_idPropertyOfTypeObjectId.class);
|
||||
template.dropCollection(PersonWith_idPropertyOfTypeString.class);
|
||||
template.dropCollection(PersonWithIdPropertyOfTypeObjectId.class);
|
||||
template.dropCollection(PersonWithIdPropertyOfTypeString.class);
|
||||
template.dropCollection(PersonWithIdPropertyOfTypeInteger.class);
|
||||
template.dropCollection(PersonWithIdPropertyOfPrimitiveInt.class);
|
||||
template.dropCollection(PersonWithIdPropertyOfTypeLong.class);
|
||||
template.dropCollection(PersonWithIdPropertyOfPrimitiveLong.class);
|
||||
template.dropCollection(PersonWithVersionPropertyOfTypeInteger.class);
|
||||
template.dropCollection(TestClass.class);
|
||||
template.dropCollection(Sample.class);
|
||||
template.dropCollection(MyPerson.class);
|
||||
template.dropCollection("collection");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -201,19 +212,14 @@ public class MongoTemplateTests {
|
||||
|
||||
template.insert(person);
|
||||
|
||||
try {
|
||||
thrown.expect(DataIntegrityViolationException.class);
|
||||
thrown.expectMessage("Execution");
|
||||
thrown.expectMessage("$push");
|
||||
thrown.expectMessage("firstName");
|
||||
|
||||
Query query = new Query(Criteria.where("firstName").is("Amol"));
|
||||
Update upd = new Update().push("age", 29);
|
||||
template.updateFirst(query, upd, Person.class);
|
||||
fail("Expected DataIntegrityViolationException!");
|
||||
|
||||
} catch (DataIntegrityViolationException e) {
|
||||
|
||||
assertThat(e.getMessage(),
|
||||
is("Execution of update with '{ \"$push\" : { \"age\" : 29}}'' using '{ \"firstName\" : \"Amol\"}' "
|
||||
+ "query failed: Cannot apply $push/$pushAll modifier to non-array"));
|
||||
}
|
||||
Query query = new Query(Criteria.where("firstName").is("Amol"));
|
||||
Update upd = new Update().push("age", 29);
|
||||
template.updateFirst(query, upd, Person.class);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1017,7 +1023,7 @@ public class MongoTemplateTests {
|
||||
assertThat(lastMongoAction.getCollectionName(), is("personWithIdPropertyOfTypeObjectId"));
|
||||
assertThat(lastMongoAction.getDefaultWriteConcern(), equalTo(WriteConcern.NONE));
|
||||
assertThat(lastMongoAction.getDocument(), notNullValue());
|
||||
assertThat(lastMongoAction.getEntityClass().toString(), is(PersonWithIdPropertyOfTypeObjectId.class.toString()));
|
||||
assertThat(lastMongoAction.getEntityType().toString(), is(PersonWithIdPropertyOfTypeObjectId.class.toString()));
|
||||
assertThat(lastMongoAction.getMongoActionOperation(), is(MongoActionOperation.UPDATE));
|
||||
assertThat(lastMongoAction.getQuery(), equalTo(q.getQueryObject()));
|
||||
|
||||
@@ -1232,6 +1238,223 @@ public class MongoTemplateTests {
|
||||
template.remove(query(where("id").is(id)), TypeWithMyId.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-506
|
||||
*/
|
||||
@Test
|
||||
public void exceutesBasicQueryCorrectly() {
|
||||
|
||||
Address address = new Address();
|
||||
address.state = "PA";
|
||||
address.city = "Philadelphia";
|
||||
|
||||
MyPerson person = new MyPerson();
|
||||
person.name = "Oleg";
|
||||
person.address = address;
|
||||
|
||||
template.save(person);
|
||||
|
||||
Query query = new BasicQuery("{'name' : 'Oleg'}");
|
||||
List<MyPerson> result = template.find(query, MyPerson.class);
|
||||
|
||||
assertThat(result, hasSize(1));
|
||||
assertThat(result.get(0), hasProperty("name", is("Oleg")));
|
||||
|
||||
query = new BasicQuery("{'address.state' : 'PA' }");
|
||||
result = template.find(query, MyPerson.class);
|
||||
|
||||
assertThat(result, hasSize(1));
|
||||
assertThat(result.get(0), hasProperty("name", is("Oleg")));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-279
|
||||
*/
|
||||
@Test(expected = OptimisticLockingFailureException.class)
|
||||
public void optimisticLockingHandling() {
|
||||
|
||||
// Init version
|
||||
PersonWithVersionPropertyOfTypeInteger person = new PersonWithVersionPropertyOfTypeInteger();
|
||||
person.age = 29;
|
||||
person.firstName = "Patryk";
|
||||
template.save(person);
|
||||
|
||||
List<PersonWithVersionPropertyOfTypeInteger> result = template
|
||||
.findAll(PersonWithVersionPropertyOfTypeInteger.class);
|
||||
|
||||
assertThat(result, hasSize(1));
|
||||
assertThat(result.get(0).version, is(0));
|
||||
|
||||
// Version change
|
||||
person = result.get(0);
|
||||
person.firstName = "Patryk2";
|
||||
|
||||
template.save(person);
|
||||
|
||||
assertThat(person.version, is(1));
|
||||
|
||||
result = mappingTemplate.findAll(PersonWithVersionPropertyOfTypeInteger.class);
|
||||
|
||||
assertThat(result, hasSize(1));
|
||||
assertThat(result.get(0).version, is(1));
|
||||
|
||||
// Optimistic lock exception
|
||||
person.version = 0;
|
||||
person.firstName = "Patryk3";
|
||||
|
||||
template.save(person);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-562
|
||||
*/
|
||||
@Test
|
||||
public void optimisticLockingHandlingWithExistingId() {
|
||||
|
||||
PersonWithVersionPropertyOfTypeInteger person = new PersonWithVersionPropertyOfTypeInteger();
|
||||
person.id = new ObjectId().toString();
|
||||
person.age = 29;
|
||||
person.firstName = "Patryk";
|
||||
template.save(person);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-539
|
||||
*/
|
||||
@Test
|
||||
public void removesObjectFromExplicitCollection() {
|
||||
|
||||
String collectionName = "explicit";
|
||||
template.remove(new Query(), collectionName);
|
||||
|
||||
PersonWithConvertedId person = new PersonWithConvertedId();
|
||||
person.name = "Dave";
|
||||
template.save(person, collectionName);
|
||||
assertThat(template.findAll(PersonWithConvertedId.class, collectionName).isEmpty(), is(false));
|
||||
|
||||
template.remove(person, collectionName);
|
||||
assertThat(template.findAll(PersonWithConvertedId.class, collectionName).isEmpty(), is(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-549
|
||||
*/
|
||||
public void savesMapCorrectly() {
|
||||
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
map.put("key", "value");
|
||||
|
||||
template.save(map, "maps");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-549
|
||||
*/
|
||||
@Test(expected = MappingException.class)
|
||||
public void savesMongoPrimitiveObjectCorrectly() {
|
||||
template.save(new Object(), "collection");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-549
|
||||
*/
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsNullObjectToBeSaved() {
|
||||
template.save(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-550
|
||||
*/
|
||||
@Test
|
||||
public void savesPlainDbObjectCorrectly() {
|
||||
|
||||
DBObject dbObject = new BasicDBObject("foo", "bar");
|
||||
template.save(dbObject, "collection");
|
||||
|
||||
assertThat(dbObject.containsField("_id"), is(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-550
|
||||
*/
|
||||
@Test(expected = InvalidDataAccessApiUsageException.class)
|
||||
public void rejectsPlainObjectWithOutExplicitCollection() {
|
||||
|
||||
DBObject dbObject = new BasicDBObject("foo", "bar");
|
||||
template.save(dbObject, "collection");
|
||||
|
||||
template.findById(dbObject.get("_id"), DBObject.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-550
|
||||
*/
|
||||
@Test
|
||||
public void readsPlainDbObjectById() {
|
||||
|
||||
DBObject dbObject = new BasicDBObject("foo", "bar");
|
||||
template.save(dbObject, "collection");
|
||||
|
||||
DBObject result = template.findById(dbObject.get("_id"), DBObject.class, "collection");
|
||||
assertThat(result.get("foo"), is(dbObject.get("foo")));
|
||||
assertThat(result.get("_id"), is(dbObject.get("_id")));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-551
|
||||
*/
|
||||
@Test
|
||||
public void writesPlainString() {
|
||||
template.save("{ 'foo' : 'bar' }", "collection");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-551
|
||||
*/
|
||||
@Test(expected = MappingException.class)
|
||||
public void rejectsNonJsonStringForSave() {
|
||||
template.save("Foobar!", "collection");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-588
|
||||
*/
|
||||
@Test
|
||||
public void initializesVersionOnInsert() {
|
||||
|
||||
PersonWithVersionPropertyOfTypeInteger person = new PersonWithVersionPropertyOfTypeInteger();
|
||||
person.firstName = "Dave";
|
||||
|
||||
template.insert(person);
|
||||
|
||||
assertThat(person.version, is(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-588
|
||||
*/
|
||||
@Test
|
||||
public void initializesVersionOnBatchInsert() {
|
||||
|
||||
PersonWithVersionPropertyOfTypeInteger person = new PersonWithVersionPropertyOfTypeInteger();
|
||||
person.firstName = "Dave";
|
||||
|
||||
template.insertAll(Arrays.asList(person));
|
||||
|
||||
assertThat(person.version, is(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-568
|
||||
*/
|
||||
@Test
|
||||
public void queryCantBeNull() {
|
||||
|
||||
List<PersonWithIdPropertyOfTypeObjectId> result = template.findAll(PersonWithIdPropertyOfTypeObjectId.class);
|
||||
assertThat(template.find(null, PersonWithIdPropertyOfTypeObjectId.class), is(result));
|
||||
}
|
||||
|
||||
static class MyId {
|
||||
|
||||
String first;
|
||||
@@ -1261,6 +1484,12 @@ public class MongoTemplateTests {
|
||||
}
|
||||
}
|
||||
|
||||
static class PersonWithConvertedId {
|
||||
|
||||
String id;
|
||||
String name;
|
||||
}
|
||||
|
||||
static enum DateTimeToDateConverter implements Converter<DateTime, Date> {
|
||||
|
||||
INSTANCE;
|
||||
@@ -1278,4 +1507,21 @@ public class MongoTemplateTests {
|
||||
return source == null ? null : new DateTime(source.getTime());
|
||||
}
|
||||
}
|
||||
|
||||
public static class MyPerson {
|
||||
|
||||
String id;
|
||||
String name;
|
||||
Address address;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
static class Address {
|
||||
|
||||
String state;
|
||||
String city;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,12 +15,13 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Matchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@@ -31,6 +32,7 @@ import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
@@ -40,6 +42,7 @@ import org.springframework.data.mongodb.MongoDbFactory;
|
||||
import org.springframework.data.mongodb.core.convert.CustomConversions;
|
||||
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
|
||||
import org.springframework.data.mongodb.core.convert.QueryMapper;
|
||||
import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexCreator;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.data.mongodb.core.query.Update;
|
||||
@@ -71,11 +74,13 @@ public class MongoTemplateUnitTests extends MongoOperationsUnitTests {
|
||||
DBCollection collection;
|
||||
|
||||
MappingMongoConverter converter;
|
||||
MongoMappingContext mappingContext;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
this.converter = new MappingMongoConverter(factory, new MongoMappingContext());
|
||||
this.mappingContext = new MongoMappingContext();
|
||||
this.converter = new MappingMongoConverter(factory, mappingContext);
|
||||
this.template = new MongoTemplate(factory, converter);
|
||||
|
||||
when(factory.getDb()).thenReturn(db);
|
||||
@@ -198,6 +203,29 @@ public class MongoTemplateUnitTests extends MongoOperationsUnitTests {
|
||||
assertThat(entity.id, is(5));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-533
|
||||
*/
|
||||
@Test
|
||||
public void registersDefaultEntityIndexCreatorIfApplicationContextHasOneForDifferentMappingContext() {
|
||||
|
||||
GenericApplicationContext applicationContext = new GenericApplicationContext();
|
||||
applicationContext.getBeanFactory().registerSingleton("foo",
|
||||
new MongoPersistentEntityIndexCreator(new MongoMappingContext(), factory));
|
||||
|
||||
MongoTemplate mongoTemplate = new MongoTemplate(factory, converter);
|
||||
mongoTemplate.setApplicationContext(applicationContext);
|
||||
|
||||
Collection<ApplicationListener<?>> listeners = applicationContext.getApplicationListeners();
|
||||
assertThat(listeners, hasSize(1));
|
||||
|
||||
ApplicationListener<?> listener = listeners.iterator().next();
|
||||
|
||||
assertThat(listener, is(instanceOf(MongoPersistentEntityIndexCreator.class)));
|
||||
MongoPersistentEntityIndexCreator creator = (MongoPersistentEntityIndexCreator) listener;
|
||||
assertThat(creator.isIndexCreatorFor(mappingContext), is(true));
|
||||
}
|
||||
|
||||
class AutogenerateableId {
|
||||
|
||||
@Id
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2012 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 org.springframework.data.mongodb.core.mapping.Version;
|
||||
|
||||
public class PersonWithVersionPropertyOfTypeInteger {
|
||||
|
||||
String id;
|
||||
String firstName;
|
||||
int age;
|
||||
|
||||
@Version
|
||||
Integer version;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PersonWithVersionPropertyOfTypeInteger [id=" + id + ", firstName=" + firstName + ", age=" + age
|
||||
+ ", version=" + version + "]";
|
||||
}
|
||||
}
|
||||
@@ -17,12 +17,13 @@ package org.springframework.data.mongodb.core;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.data.mongodb.core.SerializationUtils.*;
|
||||
import static org.springframework.data.mongodb.core.query.SerializationUtils.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.hamcrest.Matcher;
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.mongodb.core.query.SerializationUtils;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
@@ -21,7 +21,7 @@ public class TestMongoConfiguration extends AbstractMongoConfiguration {
|
||||
@Override
|
||||
@Bean
|
||||
public Mongo mongo() throws Exception {
|
||||
return new Mongo("localhost", 27017);
|
||||
return new Mongo("127.0.0.1", 27017);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -49,6 +49,7 @@ import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.annotation.PersistenceConstructor;
|
||||
import org.springframework.data.annotation.TypeAlias;
|
||||
import org.springframework.data.mapping.PropertyPath;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.mapping.model.MappingInstantiationException;
|
||||
@@ -917,7 +918,7 @@ public class MappingMongoConverterUnitTests {
|
||||
Object contacts = result.get("contacts");
|
||||
assertThat(contacts, is(instanceOf(Collection.class)));
|
||||
assertThat(((Collection<?>) contacts).size(), is(2));
|
||||
assertThat(((Collection<Object>) contacts), hasItem(nullValue()));
|
||||
assertThat((Collection<Object>) contacts, hasItem(nullValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1252,6 +1253,18 @@ public class MappingMongoConverterUnitTests {
|
||||
assertThat(values, is(arrayWithSize(2)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-497
|
||||
*/
|
||||
@Test
|
||||
public void readsEmptyCollectionIntoConstructorCorrectly() {
|
||||
|
||||
DBObject source = new BasicDBObject("attributes", new BasicDBList());
|
||||
|
||||
TypWithCollectionConstructor result = converter.read(TypWithCollectionConstructor.class, source);
|
||||
assertThat(result.attributes, is(notNullValue()));
|
||||
}
|
||||
|
||||
private static void assertSyntheticFieldValueOf(Object target, Object expected) {
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
@@ -1266,6 +1279,50 @@ public class MappingMongoConverterUnitTests {
|
||||
fail(String.format("Didn't find synthetic field on %s!", target));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMGONGO-508
|
||||
*/
|
||||
@Test
|
||||
public void eagerlyReturnsDBRefObjectIfTargetAlreadyIsOne() {
|
||||
|
||||
DB db = mock(DB.class);
|
||||
DBRef dbRef = new DBRef(db, "collection", "id");
|
||||
|
||||
org.springframework.data.mongodb.core.mapping.DBRef annotation = mock(org.springframework.data.mongodb.core.mapping.DBRef.class);
|
||||
|
||||
assertThat(converter.createDBRef(dbRef, annotation), is(dbRef));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-523
|
||||
*/
|
||||
@Test
|
||||
public void considersTypeAliasAnnotation() {
|
||||
|
||||
Aliased aliased = new Aliased();
|
||||
aliased.name = "foo";
|
||||
|
||||
DBObject result = new BasicDBObject();
|
||||
converter.write(aliased, result);
|
||||
|
||||
Object type = result.get("_class");
|
||||
assertThat(type, is(notNullValue()));
|
||||
assertThat(type.toString(), is("_"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-533
|
||||
*/
|
||||
@Test
|
||||
public void marshalsThrowableCorrectly() {
|
||||
|
||||
ThrowableWrapper wrapper = new ThrowableWrapper();
|
||||
wrapper.throwable = new Exception();
|
||||
|
||||
DBObject dbObject = new BasicDBObject();
|
||||
converter.write(wrapper, dbObject);
|
||||
}
|
||||
|
||||
static class GenericType<T> {
|
||||
T content;
|
||||
}
|
||||
@@ -1440,6 +1497,25 @@ public class MappingMongoConverterUnitTests {
|
||||
Long innerId;
|
||||
}
|
||||
|
||||
static class TypWithCollectionConstructor {
|
||||
|
||||
List<Attribute> attributes;
|
||||
|
||||
public TypWithCollectionConstructor(List<Attribute> attributes) {
|
||||
this.attributes = attributes;
|
||||
}
|
||||
}
|
||||
|
||||
@TypeAlias("_")
|
||||
static class Aliased {
|
||||
String name;
|
||||
}
|
||||
|
||||
static class ThrowableWrapper {
|
||||
|
||||
Throwable throwable;
|
||||
}
|
||||
|
||||
private class LocalDateToDateConverter implements Converter<LocalDate, Date> {
|
||||
|
||||
public Date convert(LocalDate source) {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) 2011 by the original author(s).
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -17,11 +17,14 @@ package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.data.mongodb.core.DBObjectUtils.*;
|
||||
import static org.springframework.data.mongodb.core.query.Criteria.*;
|
||||
import static org.springframework.data.mongodb.core.query.Query.*;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.bson.types.ObjectId;
|
||||
import org.junit.Before;
|
||||
@@ -31,7 +34,10 @@ import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.mongodb.MongoDbFactory;
|
||||
import org.springframework.data.mongodb.core.DBObjectUtils;
|
||||
import org.springframework.data.mongodb.core.Person;
|
||||
import org.springframework.data.mongodb.core.mapping.DBRef;
|
||||
import org.springframework.data.mongodb.core.mapping.Field;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
import org.springframework.data.mongodb.core.query.BasicQuery;
|
||||
@@ -49,11 +55,11 @@ import com.mongodb.QueryBuilder;
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
@SuppressWarnings("unused")
|
||||
public class QueryMapperUnitTests {
|
||||
|
||||
QueryMapper mapper;
|
||||
MongoMappingContext context;
|
||||
MappingMongoConverter converter;
|
||||
|
||||
@Mock
|
||||
MongoDbFactory factory;
|
||||
@@ -63,7 +69,7 @@ public class QueryMapperUnitTests {
|
||||
|
||||
context = new MongoMappingContext();
|
||||
|
||||
MappingMongoConverter converter = new MappingMongoConverter(factory, context);
|
||||
converter = new MappingMongoConverter(factory, context);
|
||||
converter.afterPropertiesSet();
|
||||
|
||||
mapper = new QueryMapper(converter);
|
||||
@@ -200,7 +206,7 @@ public class QueryMapperUnitTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doesNotHandleNestedFieldsWithDefaultIdNames() {
|
||||
public void doesHandleNestedFieldsWithDefaultIdNames() {
|
||||
|
||||
BasicDBObject dbObject = new BasicDBObject("id", new ObjectId().toString());
|
||||
dbObject.put("nested", new BasicDBObject("id", new ObjectId().toString()));
|
||||
@@ -209,7 +215,136 @@ public class QueryMapperUnitTests {
|
||||
|
||||
DBObject result = mapper.getMappedObject(dbObject, entity);
|
||||
assertThat(result.get("_id"), is(instanceOf(ObjectId.class)));
|
||||
assertThat(((DBObject) result.get("nested")).get("id"), is(instanceOf(String.class)));
|
||||
assertThat(((DBObject) result.get("nested")).get("_id"), is(instanceOf(ObjectId.class)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-493
|
||||
*/
|
||||
@Test
|
||||
public void doesNotTranslateNonIdPropertiesFor$NeCriteria() {
|
||||
|
||||
ObjectId accidentallyAnObjectId = new ObjectId();
|
||||
|
||||
Query query = Query.query(Criteria.where("id").is("id_value").and("publishers")
|
||||
.ne(accidentallyAnObjectId.toString()));
|
||||
|
||||
DBObject dbObject = mapper.getMappedObject(query.getQueryObject(), context.getPersistentEntity(UserEntity.class));
|
||||
assertThat(dbObject.get("publishers"), is(instanceOf(DBObject.class)));
|
||||
|
||||
DBObject publishers = (DBObject) dbObject.get("publishers");
|
||||
assertThat(publishers.containsField("$ne"), is(true));
|
||||
assertThat(publishers.get("$ne"), is(instanceOf(String.class)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-494
|
||||
*/
|
||||
@Test
|
||||
public void usesEntityMetadataInOr() {
|
||||
|
||||
Query query = query(new Criteria().orOperator(where("foo").is("bar")));
|
||||
DBObject result = mapper.getMappedObject(query.getQueryObject(), context.getPersistentEntity(Sample.class));
|
||||
|
||||
assertThat(result.keySet(), hasSize(1));
|
||||
assertThat(result.keySet(), hasItem("$or"));
|
||||
|
||||
BasicDBList ors = getAsDBList(result, "$or");
|
||||
assertThat(ors, hasSize(1));
|
||||
DBObject criterias = getAsDBObject(ors, 0);
|
||||
assertThat(criterias.keySet(), hasSize(1));
|
||||
assertThat(criterias.get("_id"), is(notNullValue()));
|
||||
assertThat(criterias.get("foo"), is(nullValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void translatesPropertyReferenceCorrectly() {
|
||||
|
||||
Query query = query(where("field").is(new CustomizedField()));
|
||||
DBObject result = mapper
|
||||
.getMappedObject(query.getQueryObject(), context.getPersistentEntity(CustomizedField.class));
|
||||
|
||||
assertThat(result.containsField("foo"), is(true));
|
||||
assertThat(result.keySet().size(), is(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void translatesNestedPropertyReferenceCorrectly() {
|
||||
|
||||
Query query = query(where("field.field").is(new CustomizedField()));
|
||||
DBObject result = mapper
|
||||
.getMappedObject(query.getQueryObject(), context.getPersistentEntity(CustomizedField.class));
|
||||
|
||||
assertThat(result.containsField("foo.foo"), is(true));
|
||||
assertThat(result.keySet().size(), is(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void returnsOriginalKeyIfNoPropertyReference() {
|
||||
|
||||
Query query = query(where("bar").is(new CustomizedField()));
|
||||
DBObject result = mapper
|
||||
.getMappedObject(query.getQueryObject(), context.getPersistentEntity(CustomizedField.class));
|
||||
|
||||
assertThat(result.containsField("bar"), is(true));
|
||||
assertThat(result.keySet().size(), is(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertsAssociationCorrectly() {
|
||||
|
||||
Reference reference = new Reference();
|
||||
reference.id = 5L;
|
||||
|
||||
Query query = query(where("reference").is(reference));
|
||||
DBObject object = mapper.getMappedObject(query.getQueryObject(), context.getPersistentEntity(WithDBRef.class));
|
||||
|
||||
Object referenceObject = object.get("reference");
|
||||
|
||||
assertThat(referenceObject, is(instanceOf(com.mongodb.DBRef.class)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertsNestedAssociationCorrectly() {
|
||||
|
||||
Reference reference = new Reference();
|
||||
reference.id = 5L;
|
||||
|
||||
Query query = query(where("withDbRef.reference").is(reference));
|
||||
DBObject object = mapper.getMappedObject(query.getQueryObject(),
|
||||
context.getPersistentEntity(WithDBRefWrapper.class));
|
||||
|
||||
Object referenceObject = object.get("withDbRef.reference");
|
||||
|
||||
assertThat(referenceObject, is(instanceOf(com.mongodb.DBRef.class)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertsInKeywordCorrectly() {
|
||||
|
||||
Reference first = new Reference();
|
||||
first.id = 5L;
|
||||
|
||||
Reference second = new Reference();
|
||||
second.id = 6L;
|
||||
|
||||
Query query = query(where("reference").in(first, second));
|
||||
DBObject result = mapper.getMappedObject(query.getQueryObject(), context.getPersistentEntity(WithDBRef.class));
|
||||
|
||||
DBObject reference = DBObjectUtils.getAsDBObject(result, "reference");
|
||||
assertThat(reference.containsField("$in"), is(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-570
|
||||
*/
|
||||
@Test
|
||||
public void correctlyConvertsNullReference() {
|
||||
|
||||
Query query = query(where("reference").is(null));
|
||||
DBObject object = mapper.getMappedObject(query.getQueryObject(), context.getPersistentEntity(WithDBRef.class));
|
||||
|
||||
assertThat(object.get("reference"), is(nullValue()));
|
||||
}
|
||||
|
||||
class IdWrapper {
|
||||
@@ -237,4 +372,31 @@ public class QueryMapperUnitTests {
|
||||
enum Enum {
|
||||
INSTANCE;
|
||||
}
|
||||
|
||||
class UserEntity {
|
||||
String id;
|
||||
List<String> publishers = new ArrayList<String>();
|
||||
}
|
||||
|
||||
class CustomizedField {
|
||||
|
||||
@Field("foo")
|
||||
CustomizedField field;
|
||||
}
|
||||
|
||||
class WithDBRef {
|
||||
|
||||
@DBRef
|
||||
Reference reference;
|
||||
}
|
||||
|
||||
class Reference {
|
||||
|
||||
Long id;
|
||||
}
|
||||
|
||||
class WithDBRefWrapper {
|
||||
|
||||
WithDBRef withDbRef;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2012 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.index;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.data.mongodb.core.MongoOperations;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link MongoPersistentEntityIndexCreator}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
public class MongoPersistentEntityIndexCreatorIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
@Qualifier("mongo1")
|
||||
MongoOperations templateOne;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("mongo2")
|
||||
MongoOperations templateTwo;
|
||||
|
||||
@After
|
||||
public void cleanUp() {
|
||||
templateOne.dropCollection(SampleEntity.class);
|
||||
templateTwo.dropCollection(SampleEntity.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createsIndexForConfiguredMappingContextOnly() {
|
||||
|
||||
List<IndexInfo> indexInfo = templateOne.indexOps(SampleEntity.class).getIndexInfo();
|
||||
assertThat(indexInfo, hasSize(greaterThan(0)));
|
||||
assertThat(indexInfo, Matchers.<IndexInfo> hasItem(hasProperty("name", is("prop"))));
|
||||
|
||||
indexInfo = templateTwo.indexOps("sampleEntity").getIndexInfo();
|
||||
assertThat(indexInfo, hasSize(0));
|
||||
}
|
||||
}
|
||||
@@ -24,9 +24,13 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.data.mapping.context.MappingContextEvent;
|
||||
import org.springframework.data.mongodb.MongoDbFactory;
|
||||
import org.springframework.data.mongodb.core.mapping.Field;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
@@ -40,6 +44,8 @@ public class MongoPersistentEntityIndexCreatorUnitTests {
|
||||
|
||||
@Mock
|
||||
MongoDbFactory factory;
|
||||
@Mock
|
||||
ApplicationContext context;
|
||||
|
||||
@Test
|
||||
public void buildsIndexDefinitionUsingFieldName() {
|
||||
@@ -55,6 +61,40 @@ public class MongoPersistentEntityIndexCreatorUnitTests {
|
||||
assertThat(creator.name, is("indexName"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doesNotCreateIndexForEntityComingFromDifferentMappingContext() {
|
||||
|
||||
MongoMappingContext mappingContext = new MongoMappingContext();
|
||||
|
||||
MongoMappingContext personMappingContext = new MongoMappingContext();
|
||||
personMappingContext.setInitialEntitySet(Collections.singleton(Person.class));
|
||||
personMappingContext.initialize();
|
||||
|
||||
DummyMongoPersistentEntityIndexCreator creator = new DummyMongoPersistentEntityIndexCreator(mappingContext, factory);
|
||||
|
||||
MongoPersistentEntity<?> entity = personMappingContext.getPersistentEntity(Person.class);
|
||||
MappingContextEvent<MongoPersistentEntity<?>, MongoPersistentProperty> event = new MappingContextEvent<MongoPersistentEntity<?>, MongoPersistentProperty>(
|
||||
personMappingContext, entity);
|
||||
|
||||
creator.onApplicationEvent(event);
|
||||
|
||||
assertThat(creator.indexDefinition, is(nullValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-530
|
||||
*/
|
||||
@Test
|
||||
public void isIndexCreatorForMappingContextHandedIntoConstructor() {
|
||||
|
||||
MongoMappingContext mappingContext = new MongoMappingContext();
|
||||
mappingContext.initialize();
|
||||
|
||||
MongoPersistentEntityIndexCreator creator = new DummyMongoPersistentEntityIndexCreator(mappingContext, factory);
|
||||
assertThat(creator.isIndexCreatorFor(mappingContext), is(true));
|
||||
assertThat(creator.isIndexCreatorFor(new MongoMappingContext()), is(false));
|
||||
}
|
||||
|
||||
static class Person {
|
||||
|
||||
@Indexed(name = "indexName")
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.springframework.data.mongodb.core.index;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
|
||||
@Document
|
||||
public class SampleEntity {
|
||||
|
||||
@Id
|
||||
String id;
|
||||
|
||||
@Indexed
|
||||
String prop;
|
||||
}
|
||||
@@ -68,6 +68,16 @@ public class BasicMongoPersistentPropertyUnitTests {
|
||||
getPropertyFor(ReflectionUtils.findField(Person.class, "ssn"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-553
|
||||
*/
|
||||
@Test
|
||||
public void usesPropertyAccessForThrowableCause() {
|
||||
|
||||
MongoPersistentProperty property = getPropertyFor(ReflectionUtils.findField(Throwable.class, "cause"));
|
||||
assertThat(property.usePropertyAccess(), is(true));
|
||||
}
|
||||
|
||||
private MongoPersistentProperty getPropertyFor(Field field) {
|
||||
return new BasicMongoPersistentProperty(field, null, entity, new SimpleTypeHolder());
|
||||
}
|
||||
|
||||
@@ -16,20 +16,36 @@
|
||||
|
||||
package org.springframework.data.mongodb.core.mapping;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.mapping.context.AbstractMappingContext;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
import com.mongodb.DBRef;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link MongoMappingContext}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class MongoMappingContextUnitTests {
|
||||
|
||||
@Mock
|
||||
ApplicationContext applicationContext;
|
||||
|
||||
@Test
|
||||
public void addsSelfReferencingPersistentEntityCorrectly() throws Exception {
|
||||
|
||||
@@ -46,6 +62,24 @@ public class MongoMappingContextUnitTests {
|
||||
context.getPersistentEntity(ClassWithMultipleIdProperties.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doesNotReturnPersistentEntityForMongoSimpleType() {
|
||||
|
||||
MongoMappingContext context = new MongoMappingContext();
|
||||
assertThat(context.getPersistentEntity(DBRef.class), is(nullValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void populatesAbstractMappingContextsApplicationCorrectly() {
|
||||
|
||||
MongoMappingContext context = new MongoMappingContext();
|
||||
context.setApplicationContext(applicationContext);
|
||||
|
||||
Field field = ReflectionUtils.findField(AbstractMappingContext.class, "applicationContext");
|
||||
ReflectionUtils.makeAccessible(field);
|
||||
assertThat(ReflectionUtils.getField(field, context), is(notNullValue()));
|
||||
}
|
||||
|
||||
class ClassWithMultipleIdProperties {
|
||||
|
||||
@Id
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
* Copyright 2011-2012 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.
|
||||
@@ -44,11 +44,9 @@ import com.mongodb.Mongo;
|
||||
@ContextConfiguration("classpath:infrastructure.xml")
|
||||
public class GroupByTests {
|
||||
|
||||
@Autowired
|
||||
MongoDbFactory factory;
|
||||
@Autowired MongoDbFactory factory;
|
||||
|
||||
@Autowired
|
||||
ApplicationContext applicationContext;
|
||||
@Autowired ApplicationContext applicationContext;
|
||||
|
||||
MongoTemplate mongoTemplate;
|
||||
|
||||
@@ -158,7 +156,7 @@ public class GroupByTests {
|
||||
|
||||
private void assertMapReduceResults(GroupByResults<XObject> results) {
|
||||
DBObject dboRawResults = results.getRawResults();
|
||||
String expected = "{ \"serverUsed\" : \"127.0.0.1:27017\" , \"retval\" : [ { \"x\" : 1.0 , \"count\" : 2.0} , { \"x\" : 2.0 , \"count\" : 1.0} , { \"x\" : 3.0 , \"count\" : 3.0}] , \"count\" : 6.0 , \"keys\" : 3 , \"ok\" : 1.0}";
|
||||
String expected = "{ \"serverUsed\" : \"/127.0.0.1:27017\" , \"retval\" : [ { \"x\" : 1.0 , \"count\" : 2.0} , { \"x\" : 2.0 , \"count\" : 1.0} , { \"x\" : 3.0 , \"count\" : 3.0}] , \"count\" : 6.0 , \"keys\" : 3 , \"ok\" : 1.0}";
|
||||
Assert.assertEquals(expected, dboRawResults.toString());
|
||||
|
||||
int numResults = 0;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
* Copyright 2011-2012 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.
|
||||
@@ -15,11 +15,12 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.query;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.data.mongodb.core.query.Criteria.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.domain.Sort.Direction;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DBObject;
|
||||
@@ -51,7 +52,7 @@ public class BasicQueryUnitTests {
|
||||
|
||||
BasicQuery query = new BasicQuery("{}");
|
||||
query.setSortObject(new BasicDBObject("name", -1));
|
||||
query.sort().on("lastname", Order.ASCENDING);
|
||||
query.with(new org.springframework.data.domain.Sort(Direction.ASC, "lastname"));
|
||||
|
||||
DBObject sortReference = new BasicDBObject("name", -1);
|
||||
sortReference.put("lastname", 1);
|
||||
|
||||
@@ -15,11 +15,11 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.query;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.mongodb.InvalidMongoDbApiUsageException;
|
||||
import org.springframework.data.mongodb.core.query.Criteria;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DBObject;
|
||||
@@ -58,4 +58,14 @@ public class CriteriaTests {
|
||||
Criteria c = new Criteria("name").gte("M").and("name").ne("A");
|
||||
c.getCriteriaObject();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equalIfCriteriaMatches() {
|
||||
|
||||
Criteria left = new Criteria("name").is("Foo").and("lastname").is("Bar");
|
||||
Criteria right = new Criteria("name").is("Bar").and("lastname").is("Bar");
|
||||
|
||||
assertThat(left, is(not(right)));
|
||||
assertThat(right, is(not(left)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2011 the original author or authors.
|
||||
* Copyright 2010-2012 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.
|
||||
@@ -15,10 +15,13 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.query;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.data.mongodb.core.query.Criteria.*;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.domain.Sort.Direction;
|
||||
import org.springframework.data.mongodb.InvalidMongoDbApiUsageException;
|
||||
|
||||
public class QueryTests {
|
||||
@@ -100,7 +103,7 @@ public class QueryTests {
|
||||
public void testComplexQueryWithMultipleChainedCriteria() {
|
||||
Query q = new Query(where("name").regex("^T.*").and("age").gt(20).lt(80).and("city")
|
||||
.in("Stockholm", "London", "New York"));
|
||||
String expected = "{ \"name\" : { \"$regex\" : \"^T.*\" , \"$options\" : \"\"} , \"age\" : { \"$gt\" : 20 , \"$lt\" : 80} , "
|
||||
String expected = "{ \"name\" : { \"$regex\" : \"^T.*\"} , \"age\" : { \"$gt\" : 20 , \"$lt\" : 80} , "
|
||||
+ "\"city\" : { \"$in\" : [ \"Stockholm\" , \"London\" , \"New York\"]}}";
|
||||
Assert.assertEquals(expected, q.getQueryObject().toString());
|
||||
}
|
||||
@@ -134,14 +137,37 @@ public class QueryTests {
|
||||
@Test
|
||||
public void testQueryWithRegex() {
|
||||
Query q = new Query(where("name").regex("b.*"));
|
||||
String expected = "{ \"name\" : { \"$regex\" : \"b.*\" , \"$options\" : \"\"}}";
|
||||
String expected = "{ \"name\" : { \"$regex\" : \"b.*\"}}";
|
||||
Assert.assertEquals(expected, q.getQueryObject().toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQueryWithRegexandOption() {
|
||||
public void testQueryWithRegexAndOption() {
|
||||
Query q = new Query(where("name").regex("b.*", "i"));
|
||||
String expected = "{ \"name\" : { \"$regex\" : \"b.*\" , \"$options\" : \"i\"}}";
|
||||
Assert.assertEquals(expected, q.getQueryObject().toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-538
|
||||
*/
|
||||
@Test
|
||||
@SuppressWarnings("deprecation")
|
||||
public void addsDeprecatedSortCorrectly() {
|
||||
|
||||
Query query = new Query();
|
||||
query.sort().on("foo", Order.DESCENDING);
|
||||
|
||||
assertThat(query.getSortObject().toString(), is("{ \"foo\" : -1}"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-538
|
||||
*/
|
||||
@Test
|
||||
public void addsSortCorrectly() {
|
||||
|
||||
Query query = new Query().with(new org.springframework.data.domain.Sort(Direction.DESC, "foo"));
|
||||
assertThat(query.getSortObject().toString(), is("{ \"foo\" : -1}"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2011 the original author or authors.
|
||||
* Copyright 2010-2012 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.
|
||||
@@ -15,13 +15,13 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.query;
|
||||
|
||||
import static org.springframework.data.mongodb.core.query.Order.*;
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.data.mongodb.core.query.Order.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.mongodb.core.query.Sort;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class SortTests {
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
* Copyright 2011-2013 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.
|
||||
@@ -495,4 +495,51 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
|
||||
List<Person> result = repository.findByCreatedAtLessThanManually(boyd.createdAt);
|
||||
assertThat(result.isEmpty(), is(false));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-472
|
||||
*/
|
||||
@Test
|
||||
public void findsPeopleUsingNotPredicate() {
|
||||
|
||||
List<Person> result = repository.findByLastnameNot("Matthews");
|
||||
assertThat(result, not(hasItem(dave)));
|
||||
assertThat(result, hasSize(5));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-521
|
||||
*/
|
||||
@Test
|
||||
public void executesAndQueryCorrectly() {
|
||||
|
||||
List<Person> result = repository.findByFirstnameAndLastname("Dave", "Matthews");
|
||||
|
||||
assertThat(result, hasSize(1));
|
||||
assertThat(result, hasItem(dave));
|
||||
|
||||
result = repository.findByFirstnameAndLastname("Oliver August", "Matthews");
|
||||
|
||||
assertThat(result, hasSize(1));
|
||||
assertThat(result, hasItem(oliver));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-600
|
||||
*/
|
||||
@Test
|
||||
public void readsDocumentsWithNestedPolymorphismCorrectly() {
|
||||
|
||||
UsernameAndPassword usernameAndPassword = new UsernameAndPassword();
|
||||
usernameAndPassword.username = "dave";
|
||||
usernameAndPassword.password = "btcs";
|
||||
|
||||
dave.credentials = usernameAndPassword;
|
||||
|
||||
repository.save(dave);
|
||||
|
||||
List<Person> result = repository.findByCredentials(usernameAndPassword);
|
||||
assertThat(result, hasSize(1));
|
||||
assertThat(result, hasItem(dave));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2013 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 interface Credentials {
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2011 the original author or authors.
|
||||
* Copyright 2010-2013 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.
|
||||
@@ -54,6 +54,8 @@ public class Person extends Contact {
|
||||
@DBRef
|
||||
User creator;
|
||||
|
||||
Credentials credentials;
|
||||
|
||||
public Person() {
|
||||
|
||||
this(null, null);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2012 the original author or authors.
|
||||
* Copyright 2010-2013 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.
|
||||
@@ -106,6 +106,8 @@ public interface PersonRepository extends MongoRepository<Person, String>, Query
|
||||
*/
|
||||
List<Person> findByFirstnameNotIn(Collection<String> firstnames);
|
||||
|
||||
List<Person> findByFirstnameAndLastname(String firstname, String lastname);
|
||||
|
||||
/**
|
||||
* Returns all {@link Person}s with an age between the two given values.
|
||||
*
|
||||
@@ -183,4 +185,17 @@ public interface PersonRepository extends MongoRepository<Person, String>, Query
|
||||
*/
|
||||
List<Person> findByCreatedAtAfter(Date date);
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-472
|
||||
* @param lastname
|
||||
* @return
|
||||
*/
|
||||
List<Person> findByLastnameNot(String lastname);
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-600
|
||||
* @param credentials
|
||||
* @return
|
||||
*/
|
||||
List<Person> findByCredentials(Credentials credentials);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2010-2012 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.
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2013 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 UsernameAndPassword implements Credentials {
|
||||
|
||||
String username;
|
||||
String password;
|
||||
}
|
||||
@@ -15,11 +15,13 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.repository.query;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -27,7 +29,11 @@ import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.data.mongodb.MongoDbFactory;
|
||||
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
|
||||
import org.springframework.data.mongodb.core.mapping.DBRef;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
import org.springframework.data.mongodb.repository.query.ConvertingParameterAccessor.PotentiallyConvertingIterator;
|
||||
|
||||
import com.mongodb.BasicDBList;
|
||||
|
||||
@@ -76,4 +82,66 @@ public class ConvertingParameterAccessorUnitTests {
|
||||
|
||||
assertThat(result, is((Object) reference));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-505
|
||||
*/
|
||||
@Test
|
||||
public void convertsAssociationsToDBRef() {
|
||||
|
||||
Property property = new Property();
|
||||
property.id = 5L;
|
||||
|
||||
Object result = setupAndConvert(property);
|
||||
|
||||
assertThat(result, is(instanceOf(com.mongodb.DBRef.class)));
|
||||
com.mongodb.DBRef dbRef = (com.mongodb.DBRef) result;
|
||||
assertThat(dbRef.getRef(), is("property"));
|
||||
assertThat(dbRef.getId(), is((Object) 5L));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-505
|
||||
*/
|
||||
@Test
|
||||
public void convertsAssociationsToDBRefForCollections() {
|
||||
|
||||
Property property = new Property();
|
||||
property.id = 5L;
|
||||
|
||||
Object result = setupAndConvert(Arrays.asList(property));
|
||||
|
||||
assertThat(result, is(instanceOf(Collection.class)));
|
||||
Collection<?> collection = (Collection<?>) result;
|
||||
|
||||
assertThat(collection, hasSize(1));
|
||||
Object element = collection.iterator().next();
|
||||
|
||||
assertThat(element, is(instanceOf(com.mongodb.DBRef.class)));
|
||||
com.mongodb.DBRef dbRef = (com.mongodb.DBRef) element;
|
||||
assertThat(dbRef.getRef(), is("property"));
|
||||
assertThat(dbRef.getId(), is((Object) 5L));
|
||||
}
|
||||
|
||||
private Object setupAndConvert(Object... parameters) {
|
||||
|
||||
MongoParameterAccessor delegate = new StubParameterAccessor(parameters);
|
||||
PotentiallyConvertingIterator iterator = new ConvertingParameterAccessor(converter, delegate).iterator();
|
||||
|
||||
MongoPersistentEntity<?> entity = context.getPersistentEntity(Entity.class);
|
||||
MongoPersistentProperty property = entity.getPersistentProperty("property");
|
||||
|
||||
return iterator.nextConverted(property);
|
||||
}
|
||||
|
||||
static class Entity {
|
||||
|
||||
@DBRef
|
||||
Property property;
|
||||
}
|
||||
|
||||
static class Property {
|
||||
|
||||
Long id;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
* Copyright 2011-2012 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.
|
||||
@@ -27,7 +27,6 @@ import org.springframework.data.mongodb.core.geo.Metrics;
|
||||
import org.springframework.data.mongodb.core.geo.Point;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||
import org.springframework.data.mongodb.repository.Person;
|
||||
import org.springframework.data.mongodb.repository.support.DefaultEntityInformationCreator;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.core.support.DefaultRepositoryMetadata;
|
||||
@@ -42,13 +41,12 @@ public class MongoParametersParameterAccessorUnitTests {
|
||||
private static final Distance DISTANCE = new Distance(2.5, Metrics.KILOMETERS);
|
||||
private static final RepositoryMetadata metadata = new DefaultRepositoryMetadata(PersonRepository.class);
|
||||
private static final MongoMappingContext context = new MongoMappingContext();
|
||||
private static final EntityInformationCreator creator = new DefaultEntityInformationCreator(context);
|
||||
|
||||
@Test
|
||||
public void returnsNullForDistanceIfNoneAvailable() throws NoSuchMethodException, SecurityException {
|
||||
|
||||
Method method = PersonRepository.class.getMethod("findByLocationNear", Point.class);
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, creator);
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, context);
|
||||
|
||||
MongoParameterAccessor accessor = new MongoParametersParameterAccessor(queryMethod,
|
||||
new Object[] { new Point(10, 20) });
|
||||
@@ -59,7 +57,7 @@ public class MongoParametersParameterAccessorUnitTests {
|
||||
public void returnsDistanceIfAvailable() throws NoSuchMethodException, SecurityException {
|
||||
|
||||
Method method = PersonRepository.class.getMethod("findByLocationNear", Point.class, Distance.class);
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, creator);
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, context);
|
||||
|
||||
MongoParameterAccessor accessor = new MongoParametersParameterAccessor(queryMethod, new Object[] {
|
||||
new Point(10, 20), DISTANCE });
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
* Copyright 2011-2013 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.
|
||||
@@ -46,10 +46,10 @@ import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
import org.springframework.data.mongodb.core.query.Criteria;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.data.mongodb.repository.support.DefaultEntityInformationCreator;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.core.support.DefaultRepositoryMetadata;
|
||||
import org.springframework.data.repository.query.parser.PartTree;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
|
||||
/**
|
||||
* Unit test for {@link MongoQueryCreator}.
|
||||
@@ -75,7 +75,7 @@ public class MongoQueryCreatorUnitTests {
|
||||
public Object answer(InvocationOnMock invocation) throws Throwable {
|
||||
return invocation.getArguments()[0];
|
||||
}
|
||||
}).when(converter).convertToMongoType(any());
|
||||
}).when(converter).convertToMongoType(any(), Mockito.any(TypeInformation.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -301,7 +301,7 @@ public class MongoQueryCreatorUnitTests {
|
||||
Method method = PersonRepository.class.getMethod("findByLocationNearAndFirstname", Point.class, Distance.class,
|
||||
String.class);
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, new DefaultRepositoryMetadata(PersonRepository.class),
|
||||
new DefaultEntityInformationCreator(new MongoMappingContext()));
|
||||
new MongoMappingContext());
|
||||
MongoParameterAccessor accessor = new MongoParametersParameterAccessor(queryMethod, new Object[] { point, distance,
|
||||
"Dave" });
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) 2011 by the original author(s).
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -35,7 +35,6 @@ import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||
import org.springframework.data.mongodb.repository.Address;
|
||||
import org.springframework.data.mongodb.repository.Contact;
|
||||
import org.springframework.data.mongodb.repository.Person;
|
||||
import org.springframework.data.mongodb.repository.support.DefaultEntityInformationCreator;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.core.support.DefaultRepositoryMetadata;
|
||||
|
||||
@@ -46,12 +45,11 @@ import org.springframework.data.repository.core.support.DefaultRepositoryMetadat
|
||||
*/
|
||||
public class MongoQueryMethodUnitTests {
|
||||
|
||||
EntityInformationCreator creator;
|
||||
MongoMappingContext context;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MongoMappingContext context = new MongoMappingContext();
|
||||
creator = new DefaultEntityInformationCreator(context);
|
||||
context = new MongoMappingContext();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -60,11 +58,11 @@ public class MongoQueryMethodUnitTests {
|
||||
Method method = SampleRepository.class.getMethod("method");
|
||||
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, new DefaultRepositoryMetadata(SampleRepository.class),
|
||||
creator);
|
||||
MongoEntityInformation<?, ?> entityInformation = queryMethod.getEntityInformation();
|
||||
context);
|
||||
MongoEntityMetadata<?> metadata = queryMethod.getEntityInformation();
|
||||
|
||||
assertThat(entityInformation.getJavaType(), is(typeCompatibleWith(Address.class)));
|
||||
assertThat(entityInformation.getCollectionName(), is("contact"));
|
||||
assertThat(metadata.getJavaType(), is(typeCompatibleWith(Address.class)));
|
||||
assertThat(metadata.getCollectionName(), is("contact"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -73,8 +71,8 @@ public class MongoQueryMethodUnitTests {
|
||||
Method method = SampleRepository2.class.getMethod("method");
|
||||
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, new DefaultRepositoryMetadata(SampleRepository.class),
|
||||
creator);
|
||||
MongoEntityInformation<?, ?> entityInformation = queryMethod.getEntityInformation();
|
||||
context);
|
||||
MongoEntityMetadata<?> entityInformation = queryMethod.getEntityInformation();
|
||||
|
||||
assertThat(entityInformation.getJavaType(), is(typeCompatibleWith(Person.class)));
|
||||
assertThat(entityInformation.getCollectionName(), is("person"));
|
||||
@@ -103,7 +101,7 @@ public class MongoQueryMethodUnitTests {
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsNullEntityCreator() throws Exception {
|
||||
public void rejectsNullMappingContext() throws Exception {
|
||||
Method method = PersonRepository.class.getMethod("findByFirstname", String.class, Point.class);
|
||||
new MongoQueryMethod(method, new DefaultRepositoryMetadata(PersonRepository.class), null);
|
||||
}
|
||||
@@ -115,9 +113,16 @@ public class MongoQueryMethodUnitTests {
|
||||
assertThat(method.isCollectionQuery(), is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createsMongoQueryMethodObjectForMethodReturningAnInterface() throws Exception {
|
||||
|
||||
Method method = SampleRepository2.class.getMethod("methodReturningAnInterface");
|
||||
new MongoQueryMethod(method, new DefaultRepositoryMetadata(SampleRepository2.class), context);
|
||||
}
|
||||
|
||||
private MongoQueryMethod queryMethod(String name, Class<?>... parameters) throws Exception {
|
||||
Method method = PersonRepository.class.getMethod(name, parameters);
|
||||
return new MongoQueryMethod(method, new DefaultRepositoryMetadata(PersonRepository.class), creator);
|
||||
return new MongoQueryMethod(method, new DefaultRepositoryMetadata(PersonRepository.class), context);
|
||||
}
|
||||
|
||||
interface PersonRepository extends Repository<User, Long> {
|
||||
@@ -142,5 +147,11 @@ public class MongoQueryMethodUnitTests {
|
||||
interface SampleRepository2 extends Repository<Contact, Long> {
|
||||
|
||||
List<Person> method();
|
||||
|
||||
Customer methodReturningAnInterface();
|
||||
}
|
||||
|
||||
interface Customer {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
* Copyright 2011-2012 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.
|
||||
@@ -54,8 +54,6 @@ public class StringBasedMongoQueryUnitTests {
|
||||
@Mock
|
||||
RepositoryMetadata metadata;
|
||||
@Mock
|
||||
EntityInformationCreator creator;
|
||||
@Mock
|
||||
MongoDbFactory factory;
|
||||
|
||||
MongoConverter converter;
|
||||
@@ -70,7 +68,7 @@ public class StringBasedMongoQueryUnitTests {
|
||||
public void bindsSimplePropertyCorrectly() throws Exception {
|
||||
|
||||
Method method = SampleRepository.class.getMethod("findByLastname", String.class);
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, creator);
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, converter.getMappingContext());
|
||||
StringBasedMongoQuery mongoQuery = new StringBasedMongoQuery(queryMethod, operations);
|
||||
ConvertingParameterAccessor accesor = StubParameterAccessor.getAccessor(converter, "Matthews");
|
||||
|
||||
@@ -132,7 +130,7 @@ public class StringBasedMongoQueryUnitTests {
|
||||
private StringBasedMongoQuery createQueryForMethod(String name, Class<?>... parameters) throws Exception {
|
||||
|
||||
Method method = SampleRepository.class.getMethod(name, parameters);
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, creator);
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, converter.getMappingContext());
|
||||
return new StringBasedMongoQuery(queryMethod, operations);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
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:db-factory id="dbFactory" dbname="database" />
|
||||
<mongo:mapping-converter id="converter" db-factory-ref="dbFactory" />
|
||||
<mongo:db-factory id="mongoDbFactory" dbname="database" />
|
||||
<mongo:mapping-converter id="converter" />
|
||||
|
||||
<bean class="org.springframework.data.mongodb.gridfs.GridFsTemplate">
|
||||
<constructor-arg ref="dbFactory" />
|
||||
<constructor-arg ref="mongoDbFactory" />
|
||||
<constructor-arg ref="converter" />
|
||||
</bean>
|
||||
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
log4j.rootCategory=WARN, stdout
|
||||
|
||||
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %40.40c:%4L - %m%n
|
||||
|
||||
#log4j.category.org.springframework.data=DEBUG
|
||||
|
||||
log4j.category.org.hibernate.SQL=DEBUG
|
||||
# for debugging datasource initialization
|
||||
# log4j.category.test.jdbc=DEBUG
|
||||
18
spring-data-mongodb/src/test/resources/logback.xml
Normal file
18
spring-data-mongodb/src/test/resources/logback.xml
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
|
||||
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d %5p %40.40c:%4L - %m%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!--
|
||||
<logger name="org.springframework" level="debug" />
|
||||
-->
|
||||
|
||||
<root level="error">
|
||||
<appender-ref ref="console" />
|
||||
</root>
|
||||
|
||||
</configuration>
|
||||
@@ -0,0 +1 @@
|
||||
handlers = org.slf4j.bridge.SLF4JBridgeHandler
|
||||
@@ -0,0 +1,23 @@
|
||||
<?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="mongoConverter" db-factory-ref="factory1"
|
||||
base-package="org.springframework.data.mongodb.core.index" />
|
||||
|
||||
<bean id="mongo1" class="org.springframework.data.mongodb.core.MongoTemplate">
|
||||
<constructor-arg ref="factory1" />
|
||||
<constructor-arg ref="mongoConverter" />
|
||||
</bean>
|
||||
|
||||
<bean id="mongo2" class="org.springframework.data.mongodb.core.MongoTemplate">
|
||||
<constructor-arg ref="factory2" />
|
||||
</bean>
|
||||
|
||||
<mongo:db-factory id="factory1" host="127.0.0.1" dbname="mongo-index-db1" />
|
||||
<mongo:db-factory id="factory2" host="127.0.0.1" dbname="mongo-index-db2" />
|
||||
|
||||
</beans>
|
||||
@@ -52,7 +52,7 @@
|
||||
<xi:include href="introduction/why-sd-doc.xml"/>
|
||||
<xi:include href="introduction/requirements.xml"/>
|
||||
<xi:include href="introduction/getting-started.xml"/>
|
||||
<xi:include href="https://github.com/SpringSource/spring-data-commons/raw/1.4.0.M1/src/docbkx/repositories.xml">
|
||||
<xi:include href="https://github.com/SpringSource/spring-data-commons/raw/1.4.0.RELEASE/src/docbkx/repositories.xml">
|
||||
<xi:fallback href="../../../spring-data-commons/src/docbkx/repositories.xml" />
|
||||
</xi:include>
|
||||
</part>
|
||||
@@ -72,9 +72,12 @@
|
||||
<part id="appendix">
|
||||
<title>Appendix</title>
|
||||
|
||||
<xi:include href="https://raw.github.com/SpringSource/spring-data-commons/1.4.0.M1/src/docbkx/repository-namespace-reference.xml">
|
||||
<xi:include href="https://raw.github.com/SpringSource/spring-data-commons/1.4.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/SpringSource/spring-data-commons/1.4.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>
|
||||
|
||||
</book>
|
||||
|
||||
@@ -12,17 +12,17 @@
|
||||
<title>Knowing Spring</title>
|
||||
|
||||
<para>Spring Data uses Spring framework's <ulink
|
||||
url="http://static.springframework.org/spring/docs/3.0.x/reference/spring-core.html">core</ulink>
|
||||
url="http://static.springframework.org/spring/docs/3.0.x/reference/html/spring-core.html">core</ulink>
|
||||
functionality, such as the <ulink
|
||||
url="http://static.springframework.org/spring/docs/3.0.x/reference/beans.html">IoC</ulink>
|
||||
url="http://static.springframework.org/spring/docs/3.0.x/reference/html/beans.html">IoC</ulink>
|
||||
container, <ulink
|
||||
url="http://static.springsource.org/spring/docs/3.0.x/reference/validation.html#core-convert">type
|
||||
conv ersion system</ulink>, <ulink
|
||||
url="http://static.springsource.org/spring/docs/3.0.x/reference/expressions.html">expression
|
||||
url="http://static.springsource.org/spring/docs/3.0.x/reference/html/validation.html#core-convert">type
|
||||
conversion system</ulink>, <ulink
|
||||
url="http://static.springsource.org/spring/docs/3.0.x/reference/html/expressions.html">expression
|
||||
language</ulink>, <ulink
|
||||
url="http://static.springsource.org/spring/docs/3.0.x/reference/jmx.html">JMX
|
||||
url="http://static.springsource.org/spring/docs/3.0.x/reference/html/jmx.html">JMX
|
||||
integration</ulink>, and portable <ulink
|
||||
url="http://static.springsource.org/spring/docs/3.0.x/reference/dao.html#dao-exceptions">DAO
|
||||
url="http://static.springsource.org/spring/docs/3.0.x/reference/html/dao.html#dao-exceptions">DAO
|
||||
exception hierarchy</ulink>. While it is not important to know the
|
||||
Spring APIs, understanding the concepts behind them is. At a minimum,
|
||||
the idea behind IoC should be familiar for whatever IoC container you
|
||||
|
||||
@@ -107,15 +107,14 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb</artifactId>
|
||||
<version>1.0.0.M5</version>
|
||||
<version>1.1.0.RELEASE</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</programlisting>
|
||||
</dependencies></programlisting>
|
||||
|
||||
<para>Also change the version of Spring in the pom.xml to be</para>
|
||||
|
||||
<programlisting lang="" language="xml"><spring.framework.version>3.0.6.RELEASE</spring.framework.version></programlisting>
|
||||
<programlisting lang="" language="xml"><spring.framework.version>3.1.2.RELEASE</spring.framework.version></programlisting>
|
||||
|
||||
<para>You will also need to add the location of the Spring Milestone
|
||||
repository for maven to your pom.xml which is at the same level of your
|
||||
@@ -125,7 +124,7 @@
|
||||
<repository>
|
||||
<id>spring-milestone</id>
|
||||
<name>Spring Maven MILESTONE Repository</name>
|
||||
<url>http://maven.springframework.org/milestone</url>
|
||||
<url>http://repo.springsource.org/libs-milestone</url>
|
||||
</repository>
|
||||
</repositories></programlisting>
|
||||
|
||||
@@ -133,8 +132,9 @@
|
||||
url="http://shrub.appspot.com/maven.springframework.org/milestone/org/springframework/data/">browseable
|
||||
here</ulink>.</para>
|
||||
|
||||
<para>You may also want to set the logging level to DEBUG to see some
|
||||
additional information, edit the log4j.properties file to have</para>
|
||||
<para>You may also want to set the logging level to <code>DEBUG</code> to
|
||||
see some additional information, edit the log4j.properties file to
|
||||
have</para>
|
||||
|
||||
<programlisting>log4j.category.org.springframework.data.document.mongodb=DEBUG
|
||||
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %40.40c:%4L - %m%n</programlisting>
|
||||
@@ -215,9 +215,10 @@ public class MongoApp {
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>You can instantiate the central helper class of Spring Mongo,
|
||||
<link linkend="mongo-template">MongoTemplate</link>, using the
|
||||
standard <classname>com.mongodb.Mongo</classname> object and the name
|
||||
of the database to use.</para>
|
||||
<link
|
||||
linkend="mongo-template"><classname>MongoTemplate</classname></link>,
|
||||
using the standard <classname>com.mongodb.Mongo</classname> object and
|
||||
the name of the database to use.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
@@ -241,119 +242,6 @@ public class MongoApp {
|
||||
stored document, they will be used to instantiate the object</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<section id="mongodb-required-jars">
|
||||
|
||||
|
||||
<title>Required Jars</title>
|
||||
|
||||
The following jars are required to use Spring Data MongoDB
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>spring-data-mongodb-1.0.0.RELEASE.jar</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>spring-data-commons-1.2.0.RELEASE.jar</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
In addition to the above listed Spring Data jars you need to provide the following dependencies:
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>aopalliance-1.0.0.jar</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>commons-logging-1.1.1.jar</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>mongo-java-driver-2.5.3.jar</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>spring-aop-3.0.7.RELEASE.jar</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>spring-asm-3.0.7.RELEASE.jar</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>spring-beans-3.0.7.RELEASE.jar</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>spring-context-3.0.7.RELEASE.jar</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>spring-core-3.0.7.RELEASE.jar</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>spring-expression-3.0.7.RELEASE.jar</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
<section id="mongo.migrate-m2-m3">
|
||||
<title>Migrating from M2 to M3</title>
|
||||
|
||||
<para>There were several API changes introduced in the M3 release. To
|
||||
upgrade from M2 to M3 you will need to make. For a full listing of API
|
||||
changes please refer to this <ulink
|
||||
url="http://static.springsource.org/spring-data/data-document/docs/jdiff-mongo-m2-m3/mongo-report/">JDiff
|
||||
Report</ulink>.</para>
|
||||
|
||||
<para>The major changes are with respect to MongoTemplate</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>Constructors have changed on
|
||||
<classname>MongoTemplate</classname>. <literal>MongoTemplate(Mongo,
|
||||
String, String)</literal> and <literal>MongoTemplate(Mongo, String,
|
||||
String, MongoConverter)</literal> were removed.
|
||||
<literal>MongoTemplate(Mongo, String, UserCredentials),
|
||||
MongoTemplate(MongoDbFactory), MongoTemplate(MongoDbFactory,
|
||||
MongoConverter)</literal> were added. These changes will also effect
|
||||
usage of wiring up <classname>MongoTemplate</classname> in
|
||||
<bean/> XML defintions.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><classname>MongoTemplate</classname> no longer takes a default
|
||||
collection name. The collection name is now either specified when
|
||||
the method is invoked or inferred from the Java class, either the
|
||||
class name or via mapping metadata.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Reordered parameters in some
|
||||
<classname>MongoTemplate</classname> methods to make signatures more
|
||||
consistent across the board.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Removed <classname>MongoTemplate</classname> methods that use
|
||||
<interfacename>MongoReader</interfacename> and
|
||||
<interfacename>MongoWriter</interfacename>. As an alternative
|
||||
register a Spring converter with the MappingMongoConverter. See
|
||||
<link linkend="mapping-explicit-converters">here</link> for
|
||||
details.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Added <literal>findById</literal> methods to
|
||||
<classname>MongoTemplate.</classname></para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section id="mongo.examples-repo">
|
||||
@@ -544,7 +432,6 @@ public class AppConfig {
|
||||
DB getDb() throws DataAccessException;
|
||||
|
||||
DB getDb(String dbName) throws DataAccessException;
|
||||
|
||||
}</programlisting>
|
||||
|
||||
<para>The following sections show how you can use the contiainer with
|
||||
@@ -601,7 +488,6 @@ public class MongoConfiguration {
|
||||
public @Bean MongoDbFactory mongoDbFactory() throws Exception {
|
||||
return new SimpleMongoDbFactory(new Mongo(), "database");
|
||||
}
|
||||
|
||||
}</programlisting>
|
||||
|
||||
<para>To define the username and password create an instance of
|
||||
@@ -621,10 +507,7 @@ public class MongoConfiguration {
|
||||
public @Bean MongoTemplate mongoTemplate() throws Exception {
|
||||
return new MongoTemplate(mongoDbFactory());
|
||||
}
|
||||
}
|
||||
</programlisting>
|
||||
|
||||
<para/>
|
||||
}</programlisting>
|
||||
</section>
|
||||
|
||||
<section id="mongo.mongo-db-factory-xml">
|
||||
@@ -685,8 +568,6 @@ public class MongoConfiguration {
|
||||
<bean id="anotherMongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
|
||||
<constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/>
|
||||
</bean></programlisting>
|
||||
|
||||
<para/>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -2731,4 +2612,147 @@ mongoTemplate.dropCollection("MyNewCollection"); </programlisting>
|
||||
}
|
||||
});</programlisting>
|
||||
</section>
|
||||
|
||||
<section id="gridfs">
|
||||
<title>GridFS support</title>
|
||||
|
||||
<para>MongoDB supports storing binary files inside it's filesystem GridFS.
|
||||
Spring Data MongoDB provides a
|
||||
<interfacename>GridFsOperations</interfacename> interface as well as the
|
||||
according implementation <classname>GridFsTemplate</classname> to easily
|
||||
interact with the filesystem. You can setup a
|
||||
<classname>GridFsTemplate</classname> instance by handing it a
|
||||
<interfacename>MongoDbFactory</interfacename> as well as a
|
||||
<interfacename>MongoConverter</interfacename>:</para>
|
||||
|
||||
<example>
|
||||
<title>JavaConfig setup for a GridFsTemplate</title>
|
||||
|
||||
<programlisting language="java">class GridFsConfiguration extends AbstractMongoConfiguration {
|
||||
|
||||
// … further configuration omitted
|
||||
|
||||
@Bean
|
||||
public GridFsTemplate gridFsTemplate() {
|
||||
return new GridFsTemplate(mongoDbFactory(), mappingMongoConverter());
|
||||
}
|
||||
}</programlisting>
|
||||
</example>
|
||||
|
||||
<para>An according XML configuration looks like this:</para>
|
||||
|
||||
<example>
|
||||
<title>XML configuration for a GridFsTemplate</title>
|
||||
|
||||
<programlisting language="xml"><?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:db-factory id="mongoDbFactory" dbname="database" />
|
||||
<mongo:mapping-converter id="converter" />
|
||||
|
||||
<bean class="org.springframework.data.mongodb.gridfs.GridFsTemplate">
|
||||
<constructor-arg ref="mongoDbFactory" />
|
||||
<constructor-arg ref="converter" />
|
||||
</bean>
|
||||
|
||||
</beans></programlisting>
|
||||
</example>
|
||||
|
||||
<para>You can no get the template injected and perform storing and
|
||||
retrieving operations to it.</para>
|
||||
|
||||
<example>
|
||||
<title>Using GridFsTemplate to store files</title>
|
||||
|
||||
<programlisting language="java">class GridFsClient {
|
||||
|
||||
@Autowired
|
||||
GridFsOperations operations;
|
||||
|
||||
@Test
|
||||
public void storeFileToGridFs {
|
||||
|
||||
FileMetadata metadata = new FileMetadata();
|
||||
// populate metadata
|
||||
Resource file = … // lookup File or Resource
|
||||
|
||||
operations.store(file.getInputStream(), "filename.txt", metadata);
|
||||
}
|
||||
}</programlisting>
|
||||
</example>
|
||||
|
||||
<para>The <methodname>store(…)</methodname> operations take an
|
||||
<interfacename>InputStream</interfacename>, a filename and optionally
|
||||
metadata information about the file to store. The metadata can be an
|
||||
arbitrary object which will be marshalled by the
|
||||
<interfacename>MongoConverter</interfacename> configured with the
|
||||
<classname>GridFsTemplate</classname>. Alternatively you can also provide
|
||||
a <interfacename>DBObject</interfacename> as well.</para>
|
||||
|
||||
<para>Reading files from the filesystem can either be achieved through the
|
||||
<methodname>find(…)</methodname> or
|
||||
<methodname>getResources(…)</methodname> methods. Let's have a look at the
|
||||
<methodname>find(…)</methodname> methods first. You can either find a
|
||||
single file matching a <classname>Query</classname> or multiple ones. To
|
||||
easily define file queries we provide the
|
||||
<classname>GridFsCriteria</classname> helper class. It provides static
|
||||
factory methods to encapsulate default metadata fields (e.g.
|
||||
<methodname>whereFilename()</methodname>,
|
||||
<methodname>whereContentType()</methodname>) or the custom one through
|
||||
<methodname>whereMetaData()</methodname>.</para>
|
||||
|
||||
<example>
|
||||
<title>Using GridFsTemplate to query for files</title>
|
||||
|
||||
<programlisting language="java">class GridFsClient {
|
||||
|
||||
@Autowired
|
||||
GridFsOperations operations;
|
||||
|
||||
@Test
|
||||
public void findFilesInGridFs {
|
||||
List<GridFSDBFile> result = operations.find(query(whereFilename().is("filename.txt")))
|
||||
}
|
||||
}</programlisting>
|
||||
</example>
|
||||
|
||||
<note>
|
||||
<para>Currently MongoDB does not support defining sort criterias when
|
||||
retrieving files from GridFS. Thus any sort criterias defined on the
|
||||
<classname>Query</classname> instance handed into the
|
||||
<methodname>find(…)</methodname> method will be disregarded.</para>
|
||||
</note>
|
||||
|
||||
<para>The other option to read files from the GridFs is using the methods
|
||||
introduced by the <interfacename>ResourcePatternResolver</interfacename>
|
||||
interface. They allow handing an Ant path into the method ar thus retrieve
|
||||
files matching the given pattern.</para>
|
||||
|
||||
<example>
|
||||
<title>Using GridFsTemplate to read files</title>
|
||||
|
||||
<programlisting language="java">class GridFsClient {
|
||||
|
||||
@Autowired
|
||||
GridFsOperations operations;
|
||||
|
||||
@Test
|
||||
public void readFilesFromGridFs {
|
||||
GridFsResources[] txtFiles = operations.getResources("*.txt");
|
||||
}
|
||||
}</programlisting>
|
||||
</example>
|
||||
|
||||
<para><interfacename>GridFsOperations</interfacename> extending
|
||||
<interfacename>ResourcePatternResolver</interfacename> allows the
|
||||
<classname>GridFsTemplate</classname> e.g. to be plugged into an
|
||||
<interfacename>ApplicationContext</interfacename> to read Spring Config
|
||||
files from a MongoDB.</para>
|
||||
</section>
|
||||
</chapter>
|
||||
|
||||
@@ -1,5 +1,110 @@
|
||||
Spring Data MongoDB Changelog
|
||||
=============================================
|
||||
=============================
|
||||
|
||||
Changes in version 1.1.2.GA (2013-02-08)
|
||||
----------------------------------------
|
||||
** Bug
|
||||
* [DATAMONGO-562] - Cannot create entity with OptimisticLocking (@Version) and initial id
|
||||
* [DATAMONGO-568] - MongoTemplate.find(...) method causes Nullpointer if query parameter is null
|
||||
* [DATAMONGO-570] - Query methods on @DBRef field with the qualifier isNull throws Exception
|
||||
* [DATAMONGO-578] - pom version issues in 1.1.x branch
|
||||
* [DATAMONGO-583] - Check if you are using for loop with a DBCursor
|
||||
* [DATAMONGO-585] - Exception during authentication in multithreaded access
|
||||
* [DATAMONGO-588] - MongoTemplate.insert does not initialize null versions to zero
|
||||
* [DATAMONGO-600] - Issues with polymorphism of nested types
|
||||
* [DATAMONGO-601] - CannotGetMongoDbConnectionException should not print password in logfile
|
||||
|
||||
** Improvement
|
||||
* [DATAMONGO-573] - Move to Logback for test logging
|
||||
* [DATAMONGO-580] - Polish BeanDefinitionParsers to avoid warnings in STS
|
||||
|
||||
** Task
|
||||
* [DATAMONGO-81] - Create unit tests for exception translation in MongoTemplate
|
||||
* [DATAMONGO-563] - Upgrade to MongoDB driver 2.9.2 as it fixes a serious regression introduced in 2.9.0
|
||||
* [DATAMONGO-576] - Configure java.util.logging to reduce verbose test logging
|
||||
* [DATAMONGO-590] - Clean up code in MongoTemplate
|
||||
* [DATAMONGO-608] - Release 1.1.2
|
||||
|
||||
Changes in version 1.1.1.GA (2012-10-17)
|
||||
----------------------------------------
|
||||
** Bug
|
||||
* [DATAMONGO-549] - MongoTemplate.save(…) suffers from potential NullPointException
|
||||
* [DATAMONGO-550] - MongoTemplate.save(BasicDBObject, String) results in NPE (after upgrading to 1.1.0.RELEASE
|
||||
* [DATAMONGO-551] - MongoTemplate.save(String, String) results in NPE (after upgrading to 1.1.0.RELEASE
|
||||
|
||||
** Task
|
||||
* [DATAMONGO-559] - Release 1.1.1.RELEASE
|
||||
|
||||
|
||||
Changes in version 1.1.0.GA (2012-10-10)
|
||||
----------------------------------------
|
||||
** Bug
|
||||
* [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
|
||||
* [DATAMONGO-532] - Multithreading authentication issue
|
||||
* [DATAMONGO-533] - Default MongoPersistentEntityIndexCreator not registered if ApplicationContext already contains one for different MappingContext
|
||||
* [DATAMONGO-535] - Retrieve of existing Mongo DB from Transaction is not working
|
||||
* [DATAMONGO-539] - Document remove doesn't work when giving collection name as a parameter
|
||||
|
||||
** Improvement
|
||||
* [DATAMONGO-279] - Optimistic locking using @Version field
|
||||
* [DATAMONGO-456] - XSD incorrectly states the default value for the mongo-ref attribute of the mongo:db-factory configuration element
|
||||
* [DATAMONGO-457] - broken links "Spring Data MongoDB - Reference Documentation"
|
||||
* [DATAMONGO-526] - Polish README.md
|
||||
* [DATAMONGO-529] - Improve Querydsl setup
|
||||
* [DATAMONGO-538] - Unify usage of Sort APIs in Query API
|
||||
|
||||
** New Feature
|
||||
* [DATAMONGO-389] - stable release spring-data-mongodb should work with stable spring spring-data-jpa
|
||||
|
||||
** Task
|
||||
* [DATAMONGO-484] - Migrate to latest MongoDB Java driver
|
||||
* [DATAMONGO-528] - Document GridFS support
|
||||
* [DATAMONGO-536] - Fix package cycle introduced by SerializationUtils
|
||||
* [DATAMONGO-541] - Release 1.1 GA
|
||||
* [DATAMONGO-543] - Polish reference documentation
|
||||
* [DATAMONGO-548] - Upgrade to Querydsl 2.8.0
|
||||
|
||||
|
||||
Changes in version 1.1.0.RC1 (2012-24-08)
|
||||
-----------------------------------------
|
||||
** Bug
|
||||
* [DATAMONGO-493] - Criteria.ne() method converts all value into ObjectId
|
||||
* [DATAMONGO-494] - $or/$nor expressions do not consider entity class mapping
|
||||
* [DATAMONGO-495] - JSON can't serialize Enum when printing Query in DEBUG message
|
||||
* [DATAMONGO-497] - Reading an empty List throws a MappingInstantiationException because it returns an HashSet instead of returning an ArrayList
|
||||
* [DATAMONGO-505] - Conversion of associations doesn't work for collection values
|
||||
* [DATAMONGO-508] - DBRef can accidentally get added as PersistentProperty
|
||||
* [DATAMONGO-517] - QueryMapping incorrectly translates complex keywords
|
||||
|
||||
** Improvement
|
||||
* [DATAMONGO-496] - AbstractMongoConfiguration.getMappingBasePackage() could default to config class' package
|
||||
* [DATAMONGO-499] - Namespace XSDs of current release version should refer to repositories XSD in version 1.0
|
||||
* [DATAMONGO-500] - Index creation reacts on events not intended for it
|
||||
* [DATAMONGO-502] - QueryMapper should transparently translate property names to field names
|
||||
* [DATAMONGO-509] - SimpleMongoRepository.exists(…) can be improved.
|
||||
* [DATAMONGO-510] - Criteria should only use BasicDBList internally
|
||||
* [DATAMONGO-511] - QueryMapper should correctly transform associations
|
||||
* [DATAMONGO-516] - Make Spring 3.1.2.RELEASE default Spring dependency version
|
||||
|
||||
** Task
|
||||
* [DATAMONGO-513] - Release 1.1 RC1
|
||||
|
||||
|
||||
Changes in version 1.0.4.RELEASE MongoDB (2012-08-24)
|
||||
-----------------------------------------------------
|
||||
** Bug
|
||||
* [DATAMONGO-493] - Criteria.ne() method converts all value into ObjectId
|
||||
* [DATAMONGO-494] - $or/$nor expressions do not consider entity class mapping
|
||||
* [DATAMONGO-495] - JSON can't serialize Enum when printing Query in DEBUG message
|
||||
|
||||
** Improvement
|
||||
* [DATAMONGO-499] - Namespace XSDs of current release version should refer to repositories XSD in version 1.0
|
||||
|
||||
** Task
|
||||
* [DATAMONGO-514] - Release 1.0.4.
|
||||
|
||||
Changes in version 1.1.0.M2 (2012-24-07)
|
||||
----------------------------------------
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Spring Data Document 1.0
|
||||
Copyright (c) [2010-2011] SpringSource, a division of VMware, Inc.
|
||||
Spring Data Document 1.1.2
|
||||
Copyright (c) [2010-2013] SpringSource, a division of VMware, Inc.
|
||||
|
||||
This product is licensed to you under the Apache License, Version 2.0 (the "License").
|
||||
You may not use this product except in compliance with the License.
|
||||
|
||||
Reference in New Issue
Block a user