Compare commits
87 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
26a31d07f5 | ||
|
|
aa5bdcd3fa | ||
|
|
2354b66c76 | ||
|
|
5b02bf0b51 | ||
|
|
2a061b9725 | ||
|
|
4f10d0cf05 | ||
|
|
8be3f02ab8 | ||
|
|
7baeb4bd9e | ||
|
|
05ca193331 | ||
|
|
b08990ccd0 | ||
|
|
f3770a4066 | ||
|
|
38b7a72f02 | ||
|
|
bccd9e22c0 | ||
|
|
6052571ff7 | ||
|
|
8ddbc3c206 | ||
|
|
2669dcb9bf | ||
|
|
295f7de8af | ||
|
|
7d20d640e8 | ||
|
|
704c130d94 | ||
|
|
3e5b4f25a4 | ||
|
|
22d49fea86 | ||
|
|
a224943f30 | ||
|
|
9d4c79e5c3 | ||
|
|
eff10210ed | ||
|
|
f151060773 | ||
|
|
7e6fd2e62a | ||
|
|
0cc050e966 | ||
|
|
e30eeaae79 | ||
|
|
b8cb2f74cf | ||
|
|
c876155d34 | ||
|
|
4e0c8a1525 | ||
|
|
eee7389d5c | ||
|
|
9890ac2aa5 | ||
|
|
2026cd3d22 | ||
|
|
4e8fdb97cc | ||
|
|
151441f908 | ||
|
|
abe2dddb1e | ||
|
|
ed777b53e4 | ||
|
|
855c9d4fab | ||
|
|
e0b8f5b566 | ||
|
|
82850d1605 | ||
|
|
8d0601550c | ||
|
|
282b63f7c2 | ||
|
|
0cb869ba97 | ||
|
|
c4fc32624b | ||
|
|
144000ed46 | ||
|
|
9f10921a48 | ||
|
|
c2127760cc | ||
|
|
d2f90bae5d | ||
|
|
b25fde4ff3 | ||
|
|
e23ca446a2 | ||
|
|
4c3b1951e2 | ||
|
|
3474f7e037 | ||
|
|
5308b8f446 | ||
|
|
e267f329fb | ||
|
|
234009cf53 | ||
|
|
ab4fb8477d | ||
|
|
76bec5e42d | ||
|
|
42beaaf47e | ||
|
|
f32afed779 | ||
|
|
b442abeef9 | ||
|
|
377c421052 | ||
|
|
fdef631c6e | ||
|
|
7ec61c9360 | ||
|
|
a95b9577da | ||
|
|
a02fe28644 | ||
|
|
d620546a3e | ||
|
|
f1621364b0 | ||
|
|
02578a0168 | ||
|
|
4bab7b32f2 | ||
|
|
0bda096e61 | ||
|
|
17139dcf3b | ||
|
|
bebfea0d33 | ||
|
|
885f0f4b70 | ||
|
|
a6000ee771 | ||
|
|
d4792cd680 | ||
|
|
949833a7db | ||
|
|
5abf1147e4 | ||
|
|
d65be17338 | ||
|
|
d1f915f702 | ||
|
|
58d50aa1ff | ||
|
|
0f30ffa090 | ||
|
|
496331d755 | ||
|
|
7658e1f1d3 | ||
|
|
221e03947b | ||
|
|
f0aed498d5 | ||
|
|
a62f6b8043 |
@@ -1,27 +0,0 @@
|
||||
= Contributor Code of Conduct
|
||||
|
||||
As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
|
||||
|
||||
We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality.
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery
|
||||
* Personal attacks
|
||||
* Trolling or insulting/derogatory comments
|
||||
* Public or private harassment
|
||||
* Publishing other's private information, such as physical or electronic addresses,
|
||||
without explicit permission
|
||||
* Other unethical or unprofessional conduct
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team.
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community.
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting a project maintainer at spring-code-of-conduct@pivotal.io.
|
||||
All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances.
|
||||
Maintainers are obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||
|
||||
This Code of Conduct is adapted from the http://contributor-covenant.org[Contributor Covenant], version 1.3.0, available at http://contributor-covenant.org/version/1/3/0/[contributor-covenant.org/version/1/3/0/].
|
||||
1
CONTRIBUTING.MD
Normal file
1
CONTRIBUTING.MD
Normal file
@@ -0,0 +1 @@
|
||||
You find the contribution guidelines for Spring Data projects [here](https://github.com/spring-projects/spring-data-build/blob/master/CONTRIBUTING.md).
|
||||
@@ -1,3 +0,0 @@
|
||||
= Spring Data contribution guidelines
|
||||
|
||||
You find the contribution guidelines for Spring Data projects https://github.com/spring-projects/spring-data-build/blob/master/CONTRIBUTING.adoc[here].
|
||||
55
pom.xml
55
pom.xml
@@ -5,7 +5,7 @@
|
||||
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>1.9.0.M1</version>
|
||||
<version>1.7.3.BUILD-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>Spring Data MongoDB</name>
|
||||
@@ -15,7 +15,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data.build</groupId>
|
||||
<artifactId>spring-data-parent</artifactId>
|
||||
<version>1.8.0.M1</version>
|
||||
<version>1.6.3.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
@@ -28,8 +28,8 @@
|
||||
<properties>
|
||||
<project.type>multi</project.type>
|
||||
<dist.id>spring-data-mongodb</dist.id>
|
||||
<springdata.commons>1.12.0.M1</springdata.commons>
|
||||
<mongo>2.14.0</mongo>
|
||||
<springdata.commons>1.10.3.BUILD-SNAPSHOT</springdata.commons>
|
||||
<mongo>2.13.0</mongo>
|
||||
<mongo.osgi>2.13.0</mongo.osgi>
|
||||
</properties>
|
||||
|
||||
@@ -123,7 +123,7 @@
|
||||
|
||||
<id>mongo3</id>
|
||||
<properties>
|
||||
<mongo>3.0.4</mongo>
|
||||
<mongo>3.0.2</mongo>
|
||||
</properties>
|
||||
|
||||
</profile>
|
||||
@@ -132,7 +132,7 @@
|
||||
|
||||
<id>mongo3-next</id>
|
||||
<properties>
|
||||
<mongo>3.0.5-SNAPSHOT</mongo>
|
||||
<mongo>3.0.0-SNAPSHOT</mongo>
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
@@ -143,45 +143,6 @@
|
||||
</repositories>
|
||||
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
|
||||
<id>mongo31</id>
|
||||
<properties>
|
||||
<mongo>3.1.0</mongo>
|
||||
</properties>
|
||||
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
|
||||
<id>mongo32-next</id>
|
||||
<properties>
|
||||
<mongo>3.2.0-SNAPSHOT</mongo>
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>mongo-snapshots</id>
|
||||
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>release</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.jfrog.buildinfo</groupId>
|
||||
<artifactId>artifactory-maven-plugin</artifactId>
|
||||
<inherited>false</inherited>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
|
||||
</profiles>
|
||||
|
||||
<dependencies>
|
||||
@@ -195,8 +156,8 @@
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-libs-milestone</id>
|
||||
<url>https://repo.spring.io/libs-milestone</url>
|
||||
<id>spring-libs-snapshot</id>
|
||||
<url>https://repo.spring.io/libs-snapshot</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>1.9.0.M1</version>
|
||||
<version>1.7.3.BUILD-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb</artifactId>
|
||||
<version>1.9.0.M1</version>
|
||||
<version>1.7.3.BUILD-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>1.9.0.M1</version>
|
||||
<version>1.7.3.BUILD-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>1.9.0.M1</version>
|
||||
<version>1.7.3.BUILD-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<context version="7.2.2.230">
|
||||
<context version="7.1.10.209">
|
||||
<scope type="Project" name="spring-data-mongodb">
|
||||
<element type="TypeFilterReferenceOverridden" name="Filter">
|
||||
<element type="IncludeTypePattern" name="org.springframework.data.mongodb.**"/>
|
||||
@@ -35,12 +35,6 @@
|
||||
<dependency toName="Project|spring-data-mongodb::Layer|Repositories::Subsystem|API" type="AllowedDependency"/>
|
||||
<dependency toName="Project|spring-data-mongodb::Layer|Repositories::Subsystem|Implementation" type="AllowedDependency"/>
|
||||
</element>
|
||||
<element type="Subsystem" name="CDI">
|
||||
<element type="TypeFilter" name="Assignment">
|
||||
<element type="IncludeTypePattern" name="**.cdi.**"/>
|
||||
</element>
|
||||
<stereotype name="Unrestricted"/>
|
||||
</element>
|
||||
<dependency toName="Project|spring-data-mongodb::Layer|Config" type="AllowedDependency"/>
|
||||
<dependency toName="Project|spring-data-mongodb::Layer|Core" type="AllowedDependency"/>
|
||||
</element>
|
||||
@@ -82,11 +76,6 @@
|
||||
</element>
|
||||
<dependency toName="Project|spring-data-mongodb::Layer|Core::Subsystem|Geospatial" type="AllowedDependency"/>
|
||||
</element>
|
||||
<element type="Subsystem" name="Script">
|
||||
<element type="TypeFilter" name="Assignment">
|
||||
<element type="IncludeTypePattern" name="**.script.**"/>
|
||||
</element>
|
||||
</element>
|
||||
<element type="Subsystem" name="Conversion">
|
||||
<element type="TypeFilter" name="Assignment">
|
||||
<element type="IncludeTypePattern" name="**.core.convert.**"/>
|
||||
@@ -94,7 +83,6 @@
|
||||
<dependency toName="Project|spring-data-mongodb::Layer|Core::Subsystem|Geospatial" type="AllowedDependency"/>
|
||||
<dependency toName="Project|spring-data-mongodb::Layer|Core::Subsystem|Mapping" type="AllowedDependency"/>
|
||||
<dependency toName="Project|spring-data-mongodb::Layer|Core::Subsystem|Query" type="AllowedDependency"/>
|
||||
<dependency toName="Project|spring-data-mongodb::Layer|Core::Subsystem|Script" type="AllowedDependency"/>
|
||||
</element>
|
||||
<element type="Subsystem" name="SpEL">
|
||||
<element type="TypeFilter" name="Assignment">
|
||||
@@ -117,11 +105,6 @@
|
||||
<dependency toName="Project|spring-data-mongodb::Layer|Core::Subsystem|Mapping" type="AllowedDependency"/>
|
||||
<dependency toName="Project|spring-data-mongodb::Layer|Core::Subsystem|Query" type="AllowedDependency"/>
|
||||
</element>
|
||||
<element type="Subsystem" name="MapReduce">
|
||||
<element type="TypeFilter" name="Assignment">
|
||||
<element type="IncludeTypePattern" name="**.mapreduce.**"/>
|
||||
</element>
|
||||
</element>
|
||||
<element type="Subsystem" name="Core">
|
||||
<element type="TypeFilter" name="Assignment">
|
||||
<element type="WeakTypePattern" name="**.core.**"/>
|
||||
@@ -130,10 +113,8 @@
|
||||
<dependency toName="Project|spring-data-mongodb::Layer|Core::Subsystem|Conversion" type="AllowedDependency"/>
|
||||
<dependency toName="Project|spring-data-mongodb::Layer|Core::Subsystem|Geospatial" type="AllowedDependency"/>
|
||||
<dependency toName="Project|spring-data-mongodb::Layer|Core::Subsystem|Index" type="AllowedDependency"/>
|
||||
<dependency toName="Project|spring-data-mongodb::Layer|Core::Subsystem|MapReduce" type="AllowedDependency"/>
|
||||
<dependency toName="Project|spring-data-mongodb::Layer|Core::Subsystem|Mapping" type="AllowedDependency"/>
|
||||
<dependency toName="Project|spring-data-mongodb::Layer|Core::Subsystem|Query" type="AllowedDependency"/>
|
||||
<dependency toName="Project|spring-data-mongodb::Layer|Core::Subsystem|Script" type="AllowedDependency"/>
|
||||
</element>
|
||||
<element type="Subsystem" name="Util">
|
||||
<element type="TypeFilter" name="Assignment">
|
||||
@@ -188,32 +169,7 @@
|
||||
</element>
|
||||
<element type="Subsystem" name="Querydsl">
|
||||
<element type="TypeFilter" name="Assignment">
|
||||
<element type="IncludeTypePattern" name="com.querydsl.**"/>
|
||||
</element>
|
||||
</element>
|
||||
<element type="Subsystem" name="Slf4j">
|
||||
<element type="TypeFilter" name="Assignment">
|
||||
<element type="IncludeTypePattern" name="org.slf4j.**"/>
|
||||
</element>
|
||||
</element>
|
||||
<element type="Subsystem" name="Jackson">
|
||||
<element type="TypeFilter" name="Assignment">
|
||||
<element type="IncludeTypePattern" name="com.fasterxml.jackson.**"/>
|
||||
</element>
|
||||
</element>
|
||||
<element type="Subsystem" name="DOM">
|
||||
<element type="TypeFilter" name="Assignment">
|
||||
<element type="IncludeTypePattern" name="org.w3c.dom.**"/>
|
||||
</element>
|
||||
</element>
|
||||
<element type="Subsystem" name="AOP Alliance">
|
||||
<element type="TypeFilter" name="Assignment">
|
||||
<element type="IncludeTypePattern" name="org.aopalliance.**"/>
|
||||
</element>
|
||||
</element>
|
||||
<element type="Subsystem" name="Guava">
|
||||
<element type="TypeFilter" name="Assignment">
|
||||
<element type="IncludeTypePattern" name="com.google.common.**"/>
|
||||
<element type="IncludeTypePattern" name="com.mysema.query.**"/>
|
||||
</element>
|
||||
</element>
|
||||
</architecture>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>1.9.0.M1</version>
|
||||
<version>1.7.3.BUILD-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -59,14 +59,14 @@
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.querydsl</groupId>
|
||||
<groupId>com.mysema.querydsl</groupId>
|
||||
<artifactId>querydsl-mongodb</artifactId>
|
||||
<version>${querydsl}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.querydsl</groupId>
|
||||
<groupId>com.mysema.querydsl</groupId>
|
||||
<artifactId>querydsl-apt</artifactId>
|
||||
<version>${querydsl}</version>
|
||||
<scope>provided</scope>
|
||||
@@ -183,7 +183,7 @@
|
||||
<version>${apt}</version>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.querydsl</groupId>
|
||||
<groupId>com.mysema.querydsl</groupId>
|
||||
<artifactId>querydsl-apt</artifactId>
|
||||
<version>${querydsl}</version>
|
||||
</dependency>
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 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;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
|
||||
import com.mongodb.BulkWriteError;
|
||||
import com.mongodb.BulkWriteException;
|
||||
import com.mongodb.BulkWriteResult;
|
||||
|
||||
/**
|
||||
* Is thrown when errors occur during bulk operations.
|
||||
*
|
||||
* @author Tobias Trelle
|
||||
* @author Oliver Gierke
|
||||
* @since 1.9
|
||||
*/
|
||||
public class BulkOperationException extends DataAccessException {
|
||||
|
||||
private static final long serialVersionUID = 73929601661154421L;
|
||||
|
||||
private final List<BulkWriteError> errors;
|
||||
private final BulkWriteResult result;
|
||||
|
||||
/**
|
||||
* Creates a new {@link BulkOperationException} with the given message and source {@link BulkWriteException}.
|
||||
*
|
||||
* @param message must not be {@literal null}.
|
||||
* @param source must not be {@literal null}.
|
||||
*/
|
||||
public BulkOperationException(String message, BulkWriteException source) {
|
||||
|
||||
super(message, source);
|
||||
|
||||
this.errors = source.getWriteErrors();
|
||||
this.result = source.getWriteResult();
|
||||
}
|
||||
|
||||
public List<BulkWriteError> getErrors() {
|
||||
return errors;
|
||||
}
|
||||
|
||||
public BulkWriteResult getResult() {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2015 by the original author(s).
|
||||
* Copyright 2011-2014 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.
|
||||
@@ -18,10 +18,6 @@ package org.springframework.data.mongodb.config;
|
||||
import static org.springframework.data.config.ParsingUtils.*;
|
||||
import static org.springframework.data.mongodb.config.MongoParsingUtils.*;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||
@@ -38,7 +34,6 @@ import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import com.mongodb.Mongo;
|
||||
import com.mongodb.MongoClientURI;
|
||||
import com.mongodb.MongoURI;
|
||||
|
||||
/**
|
||||
@@ -47,22 +42,9 @@ import com.mongodb.MongoURI;
|
||||
* @author Jon Brisbin
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Darimont
|
||||
* @author Christoph Strobl
|
||||
* @author Viktor Khoroshko
|
||||
*/
|
||||
public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
|
||||
|
||||
private static final Set<String> MONGO_URI_ALLOWED_ADDITIONAL_ATTRIBUTES;
|
||||
|
||||
static {
|
||||
|
||||
Set<String> mongoUriAllowedAdditionalAttributes = new HashSet<String>();
|
||||
mongoUriAllowedAdditionalAttributes.add("id");
|
||||
mongoUriAllowedAdditionalAttributes.add("write-concern");
|
||||
|
||||
MONGO_URI_ALLOWED_ADDITIONAL_ATTRIBUTES = Collections.unmodifiableSet(mongoUriAllowedAdditionalAttributes);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#resolveId(org.w3c.dom.Element, org.springframework.beans.factory.support.AbstractBeanDefinition, org.springframework.beans.factory.xml.ParserContext)
|
||||
@@ -82,25 +64,29 @@ public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
|
||||
@Override
|
||||
protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
|
||||
|
||||
// Common setup
|
||||
BeanDefinitionBuilder dbFactoryBuilder = BeanDefinitionBuilder.genericBeanDefinition(SimpleMongoDbFactory.class);
|
||||
setPropertyValue(dbFactoryBuilder, element, "write-concern", "writeConcern");
|
||||
|
||||
BeanDefinition mongoUri = getMongoUri(element, parserContext);
|
||||
|
||||
if (mongoUri != null) {
|
||||
|
||||
dbFactoryBuilder.addConstructorArgValue(mongoUri);
|
||||
return getSourceBeanDefinition(dbFactoryBuilder, parserContext, element);
|
||||
}
|
||||
Object source = parserContext.extractSource(element);
|
||||
|
||||
BeanComponentDefinitionBuilder helper = new BeanComponentDefinitionBuilder(element, parserContext);
|
||||
|
||||
String uri = element.getAttribute("uri");
|
||||
String mongoRef = element.getAttribute("mongo-ref");
|
||||
String dbname = element.getAttribute("dbname");
|
||||
|
||||
BeanDefinition userCredentials = getUserCredentialsBeanDefinition(element, parserContext);
|
||||
|
||||
// Common setup
|
||||
BeanDefinitionBuilder dbFactoryBuilder = BeanDefinitionBuilder.genericBeanDefinition(SimpleMongoDbFactory.class);
|
||||
setPropertyValue(dbFactoryBuilder, element, "write-concern", "writeConcern");
|
||||
|
||||
if (StringUtils.hasText(uri)) {
|
||||
if (StringUtils.hasText(mongoRef) || StringUtils.hasText(dbname) || userCredentials != null) {
|
||||
parserContext.getReaderContext().error("Configure either Mongo URI or details individually!", source);
|
||||
}
|
||||
|
||||
dbFactoryBuilder.addConstructorArgValue(getMongoUri(uri));
|
||||
return getSourceBeanDefinition(dbFactoryBuilder, parserContext, element);
|
||||
}
|
||||
|
||||
// Defaulting
|
||||
if (StringUtils.hasText(mongoRef)) {
|
||||
dbFactoryBuilder.addConstructorArgReference(mongoRef);
|
||||
@@ -161,42 +147,14 @@ public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link BeanDefinition} for a {@link MongoURI} or {@link MongoClientURI} depending on configured
|
||||
* attributes. <br />
|
||||
* Errors when configured element contains {@literal uri} or {@literal client-uri} along with other attributes except
|
||||
* {@literal write-concern} and/or {@literal id}.
|
||||
* Creates a {@link BeanDefinition} for a {@link MongoURI}.
|
||||
*
|
||||
* @param element must not be {@literal null}.
|
||||
* @param parserContext
|
||||
* @return {@literal null} in case no client-/uri defined.
|
||||
* @param uri
|
||||
* @return
|
||||
*/
|
||||
private BeanDefinition getMongoUri(Element element, ParserContext parserContext) {
|
||||
private BeanDefinition getMongoUri(String uri) {
|
||||
|
||||
boolean hasClientUri = element.hasAttribute("client-uri");
|
||||
|
||||
if (!hasClientUri && !element.hasAttribute("uri")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int allowedAttributesCount = 1;
|
||||
for (String attribute : MONGO_URI_ALLOWED_ADDITIONAL_ATTRIBUTES) {
|
||||
|
||||
if (element.hasAttribute(attribute)) {
|
||||
allowedAttributesCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (element.getAttributes().getLength() > allowedAttributesCount) {
|
||||
|
||||
parserContext.getReaderContext().error(
|
||||
"Configure either " + (hasClientUri ? "Mongo Client URI" : "Mongo URI") + " or details individually!",
|
||||
parserContext.extractSource(element));
|
||||
}
|
||||
|
||||
Class<?> type = hasClientUri ? MongoClientURI.class : MongoURI.class;
|
||||
String uri = hasClientUri ? element.getAttribute("client-uri") : element.getAttribute("uri");
|
||||
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(type);
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MongoURI.class);
|
||||
builder.addConstructorArgValue(uri);
|
||||
|
||||
return builder.getBeanDefinition();
|
||||
|
||||
@@ -1,145 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 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 java.util.List;
|
||||
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.data.mongodb.core.query.Update;
|
||||
import org.springframework.data.util.Tuple;
|
||||
|
||||
import com.mongodb.BulkWriteResult;
|
||||
|
||||
/**
|
||||
* Bulk operations for insert/update/remove actions on a collection. These bulks operation are available since MongoDB
|
||||
* 2.6 and make use of low level bulk commands on the protocol level. This interface defines a fluent API to add
|
||||
* multiple single operations or list of similar operations in sequence which can then eventually be executed by calling
|
||||
* {@link #execute()}.
|
||||
*
|
||||
* @author Tobias Trelle
|
||||
* @author Oliver Gierke
|
||||
* @since 1.9
|
||||
*/
|
||||
public interface BulkOperations {
|
||||
|
||||
/**
|
||||
* Mode for bulk operation.
|
||||
**/
|
||||
public enum BulkMode {
|
||||
|
||||
/** Perform bulk operations in sequence. The first error will cancel processing. */
|
||||
ORDERED,
|
||||
|
||||
/** Perform bulk operations in parallel. Processing will continue on errors. */
|
||||
UNORDERED
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a single insert to the bulk operation.
|
||||
*
|
||||
* @param documents the document to insert, must not be {@literal null}.
|
||||
* @return the current {@link BulkOperations} instance with the insert added, will never be {@literal null}.
|
||||
*/
|
||||
BulkOperations insert(Object documents);
|
||||
|
||||
/**
|
||||
* Add a list of inserts to the bulk operation.
|
||||
*
|
||||
* @param documents List of documents to insert, must not be {@literal null}.
|
||||
* @return the current {@link BulkOperations} instance with the insert added, will never be {@literal null}.
|
||||
*/
|
||||
BulkOperations insert(List<? extends Object> documents);
|
||||
|
||||
/**
|
||||
* Add a single update to the bulk operation. For the update request, only the first matching document is updated.
|
||||
*
|
||||
* @param query update criteria, must not be {@literal null}.
|
||||
* @param update {@link Update} operation to perform, must not be {@literal null}.
|
||||
* @return the current {@link BulkOperations} instance with the update added, will never be {@literal null}.
|
||||
*/
|
||||
BulkOperations updateOne(Query query, Update update);
|
||||
|
||||
/**
|
||||
* Add a list of updates to the bulk operation. For each update request, only the first matching document is updated.
|
||||
*
|
||||
* @param updates Update operations to perform.
|
||||
* @return the current {@link BulkOperations} instance with the update added, will never be {@literal null}.
|
||||
*/
|
||||
BulkOperations updateOne(List<Tuple<Query, Update>> updates);
|
||||
|
||||
/**
|
||||
* Add a single update to the bulk operation. For the update request, all matching documents are updated.
|
||||
*
|
||||
* @param query Update criteria.
|
||||
* @param update Update operation to perform.
|
||||
* @return the current {@link BulkOperations} instance with the update added, will never be {@literal null}.
|
||||
*/
|
||||
BulkOperations updateMulti(Query query, Update update);
|
||||
|
||||
/**
|
||||
* Add a list of updates to the bulk operation. For each update request, all matching documents are updated.
|
||||
*
|
||||
* @param updates Update operations to perform.
|
||||
* @return The bulk operation.
|
||||
* @return the current {@link BulkOperations} instance with the update added, will never be {@literal null}.
|
||||
*/
|
||||
BulkOperations updateMulti(List<Tuple<Query, Update>> updates);
|
||||
|
||||
/**
|
||||
* Add a single upsert to the bulk operation. An upsert is an update if the set of matching documents is not empty,
|
||||
* else an insert.
|
||||
*
|
||||
* @param query Update criteria.
|
||||
* @param update Update operation to perform.
|
||||
* @return The bulk operation.
|
||||
* @return the current {@link BulkOperations} instance with the update added, will never be {@literal null}.
|
||||
*/
|
||||
BulkOperations upsert(Query query, Update update);
|
||||
|
||||
/**
|
||||
* Add a list of upserts to the bulk operation. An upsert is an update if the set of matching documents is not empty,
|
||||
* else an insert.
|
||||
*
|
||||
* @param updates Updates/insert operations to perform.
|
||||
* @return The bulk operation.
|
||||
* @return the current {@link BulkOperations} instance with the update added, will never be {@literal null}.
|
||||
*/
|
||||
BulkOperations upsert(List<Tuple<Query, Update>> updates);
|
||||
|
||||
/**
|
||||
* Add a single remove operation to the bulk operation.
|
||||
*
|
||||
* @param remove the {@link Query} to select the documents to be removed, must not be {@literal null}.
|
||||
* @return the current {@link BulkOperations} instance with the removal added, will never be {@literal null}.
|
||||
*/
|
||||
BulkOperations remove(Query remove);
|
||||
|
||||
/**
|
||||
* Add a list of remove operations to the bulk operation.
|
||||
*
|
||||
* @param removes the remove operations to perform, must not be {@literal null}.
|
||||
* @return the current {@link BulkOperations} instance with the removal added, will never be {@literal null}.
|
||||
*/
|
||||
BulkOperations remove(List<Query> removes);
|
||||
|
||||
/**
|
||||
* Execute all bulk operations using the default write concern.
|
||||
*
|
||||
* @return Result of the bulk operation providing counters for inserts/updates etc.
|
||||
* @throws {@link BulkOperationException} if an error occurred during bulk processing.
|
||||
*/
|
||||
BulkWriteResult execute();
|
||||
}
|
||||
@@ -1,327 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 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 java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.data.mongodb.core.query.Update;
|
||||
import org.springframework.data.util.Tuple;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.mongodb.BulkWriteException;
|
||||
import com.mongodb.BulkWriteOperation;
|
||||
import com.mongodb.BulkWriteRequestBuilder;
|
||||
import com.mongodb.BulkWriteResult;
|
||||
import com.mongodb.DBCollection;
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.WriteConcern;
|
||||
|
||||
/**
|
||||
* Default implementation for {@link BulkOperations}.
|
||||
*
|
||||
* @author Tobias Trelle
|
||||
* @author Oliver Gierke
|
||||
* @since 1.9
|
||||
*/
|
||||
class DefaultBulkOperations implements BulkOperations {
|
||||
|
||||
private final MongoOperations mongoOperations;
|
||||
private final BulkMode bulkMode;
|
||||
private final String collectionName;
|
||||
private final Class<?> entityType;
|
||||
|
||||
private PersistenceExceptionTranslator exceptionTranslator;
|
||||
private WriteConcernResolver writeConcernResolver;
|
||||
private WriteConcern defaultWriteConcern;
|
||||
|
||||
private BulkWriteOperation bulk;
|
||||
|
||||
/**
|
||||
* Creates a new {@link DefaultBulkOperations} for the given {@link MongoOperations}, {@link BulkMode}, collection
|
||||
* name and {@link WriteConcern}.
|
||||
*
|
||||
* @param mongoOperations The underlying {@link MongoOperations}, must not be {@literal null}.
|
||||
* @param bulkMode must not be {@literal null}.
|
||||
* @param collectionName Name of the collection to work on, must not be {@literal null} or empty.
|
||||
* @param entityType the entity type, can be {@literal null}.
|
||||
*/
|
||||
DefaultBulkOperations(MongoOperations mongoOperations, BulkMode bulkMode, String collectionName,
|
||||
Class<?> entityType) {
|
||||
|
||||
Assert.notNull(mongoOperations, "MongoOperations must not be null!");
|
||||
Assert.notNull(bulkMode, "BulkMode must not be null!");
|
||||
Assert.hasText(collectionName, "Collection name must not be null or empty!");
|
||||
|
||||
this.mongoOperations = mongoOperations;
|
||||
this.bulkMode = bulkMode;
|
||||
this.collectionName = collectionName;
|
||||
this.entityType = entityType;
|
||||
|
||||
this.exceptionTranslator = new MongoExceptionTranslator();
|
||||
this.writeConcernResolver = DefaultWriteConcernResolver.INSTANCE;
|
||||
|
||||
this.bulk = initBulkOperation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the {@link PersistenceExceptionTranslator} to be used. Defaults to {@link MongoExceptionTranslator}.
|
||||
*
|
||||
* @param exceptionTranslator can be {@literal null}.
|
||||
*/
|
||||
public void setExceptionTranslator(PersistenceExceptionTranslator exceptionTranslator) {
|
||||
this.exceptionTranslator = exceptionTranslator == null ? new MongoExceptionTranslator() : exceptionTranslator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the {@link WriteConcernResolver} to be used. Defaults to {@link DefaultWriteConcernResolver}.
|
||||
*
|
||||
* @param writeConcernResolver can be {@literal null}.
|
||||
*/
|
||||
public void setWriteConcernResolver(WriteConcernResolver writeConcernResolver) {
|
||||
this.writeConcernResolver = writeConcernResolver == null ? DefaultWriteConcernResolver.INSTANCE
|
||||
: writeConcernResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the default {@link WriteConcern} to be used. Defaults to {@literal null}.
|
||||
*
|
||||
* @param defaultWriteConcern can be {@literal null}.
|
||||
*/
|
||||
public void setDefaultWriteConcern(WriteConcern defaultWriteConcern) {
|
||||
this.defaultWriteConcern = defaultWriteConcern;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.BulkOperations#insert(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public BulkOperations insert(Object document) {
|
||||
|
||||
Assert.notNull(document, "Document must not be null!");
|
||||
|
||||
bulk.insert((DBObject) mongoOperations.getConverter().convertToMongoType(document));
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.BulkOperations#insert(java.util.List)
|
||||
*/
|
||||
@Override
|
||||
public BulkOperations insert(List<? extends Object> documents) {
|
||||
|
||||
Assert.notNull(documents, "Documents must not be null!");
|
||||
|
||||
for (Object document : documents) {
|
||||
insert(document);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.BulkOperations#updateOne(org.springframework.data.mongodb.core.query.Query, org.springframework.data.mongodb.core.query.Update)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public BulkOperations updateOne(Query query, Update update) {
|
||||
|
||||
Assert.notNull(query, "Query must not be null!");
|
||||
Assert.notNull(update, "Update must not be null!");
|
||||
|
||||
return updateOne(Arrays.asList(Tuple.of(query, update)));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.BulkOperations#updateOne(java.util.List)
|
||||
*/
|
||||
@Override
|
||||
public BulkOperations updateOne(List<Tuple<Query, Update>> updates) {
|
||||
|
||||
Assert.notNull(updates, "Updates must not be null!");
|
||||
|
||||
for (Tuple<Query, Update> update : updates) {
|
||||
update(update.getFirst(), update.getSecond(), false, false);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.BulkOperations#updateMulti(org.springframework.data.mongodb.core.query.Query, org.springframework.data.mongodb.core.query.Update)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public BulkOperations updateMulti(Query query, Update update) {
|
||||
|
||||
Assert.notNull(query, "Query must not be null!");
|
||||
Assert.notNull(update, "Update must not be null!");
|
||||
|
||||
return updateMulti(Arrays.asList(Tuple.of(query, update)));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.BulkOperations#updateMulti(java.util.List)
|
||||
*/
|
||||
@Override
|
||||
public BulkOperations updateMulti(List<Tuple<Query, Update>> updates) {
|
||||
|
||||
Assert.notNull(updates, "Updates must not be null!");
|
||||
|
||||
for (Tuple<Query, Update> update : updates) {
|
||||
update(update.getFirst(), update.getSecond(), false, true);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.BulkOperations#upsert(org.springframework.data.mongodb.core.query.Query, org.springframework.data.mongodb.core.query.Update)
|
||||
*/
|
||||
@Override
|
||||
public BulkOperations upsert(Query query, Update update) {
|
||||
return update(query, update, true, true);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.BulkOperations#upsert(java.util.List)
|
||||
*/
|
||||
@Override
|
||||
public BulkOperations upsert(List<Tuple<Query, Update>> updates) {
|
||||
|
||||
for (Tuple<Query, Update> update : updates) {
|
||||
upsert(update.getFirst(), update.getSecond());
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.BulkOperations#remove(org.springframework.data.mongodb.core.query.Query)
|
||||
*/
|
||||
@Override
|
||||
public BulkOperations remove(Query query) {
|
||||
|
||||
Assert.notNull(query, "Query must not be null!");
|
||||
|
||||
bulk.find(query.getQueryObject()).remove();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.BulkOperations#remove(java.util.List)
|
||||
*/
|
||||
@Override
|
||||
public BulkOperations remove(List<Query> removes) {
|
||||
|
||||
Assert.notNull(removes, "Removals must not be null!");
|
||||
|
||||
for (Query query : removes) {
|
||||
remove(query);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.BulkOperations#executeBulk()
|
||||
*/
|
||||
@Override
|
||||
public BulkWriteResult execute() {
|
||||
|
||||
MongoAction action = new MongoAction(defaultWriteConcern, MongoActionOperation.BULK, collectionName, entityType,
|
||||
null, null);
|
||||
WriteConcern writeConcern = writeConcernResolver.resolve(action);
|
||||
|
||||
try {
|
||||
|
||||
return writeConcern == null ? bulk.execute() : bulk.execute(writeConcern);
|
||||
|
||||
} catch (BulkWriteException o_O) {
|
||||
|
||||
DataAccessException toThrow = exceptionTranslator.translateExceptionIfPossible(o_O);
|
||||
throw toThrow == null ? o_O : toThrow;
|
||||
|
||||
} finally {
|
||||
this.bulk = initBulkOperation();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs update and upsert bulk operations.
|
||||
*
|
||||
* @param query the {@link Query} to determine documents to update.
|
||||
* @param update the {@link Update} to perform, must not be {@literal null}.
|
||||
* @param upsert whether to upsert.
|
||||
* @param multi whether to issue a multi-update.
|
||||
* @return the {@link BulkOperations} with the update registered.
|
||||
*/
|
||||
private BulkOperations update(Query query, Update update, boolean upsert, boolean multi) {
|
||||
|
||||
Assert.notNull(query, "Query must not be null!");
|
||||
Assert.notNull(update, "Update must not be null!");
|
||||
|
||||
BulkWriteRequestBuilder builder = bulk.find(query.getQueryObject());
|
||||
|
||||
if (upsert) {
|
||||
|
||||
if (multi) {
|
||||
builder.upsert().update(update.getUpdateObject());
|
||||
} else {
|
||||
builder.upsert().updateOne(update.getUpdateObject());
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (multi) {
|
||||
builder.update(update.getUpdateObject());
|
||||
} else {
|
||||
builder.updateOne(update.getUpdateObject());
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
private final BulkWriteOperation initBulkOperation() {
|
||||
|
||||
DBCollection collection = mongoOperations.getCollection(collectionName);
|
||||
|
||||
switch (bulkMode) {
|
||||
case ORDERED:
|
||||
return collection.initializeOrderedBulkOperation();
|
||||
case UNORDERED:
|
||||
return collection.initializeUnorderedBulkOperation();
|
||||
}
|
||||
|
||||
throw new IllegalStateException("BulkMode was null!");
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 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 com.mongodb.WriteConcern;
|
||||
|
||||
/**
|
||||
* Default {@link WriteConcernResolver} resolving the {@link WriteConcern} from the given {@link MongoAction}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
enum DefaultWriteConcernResolver implements WriteConcernResolver {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
public WriteConcern resolve(MongoAction action) {
|
||||
return action.getDefaultWriteConcern();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2015 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,5 +25,5 @@ package org.springframework.data.mongodb.core;
|
||||
*/
|
||||
public enum MongoActionOperation {
|
||||
|
||||
REMOVE, UPDATE, INSERT, INSERT_LIST, SAVE, BULK;
|
||||
REMOVE, UPDATE, INSERT, INSERT_LIST, SAVE
|
||||
}
|
||||
|
||||
@@ -25,14 +25,10 @@ import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.dao.InvalidDataAccessResourceUsageException;
|
||||
import org.springframework.dao.PermissionDeniedDataAccessException;
|
||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||
import org.springframework.data.mongodb.BulkOperationException;
|
||||
import org.springframework.data.mongodb.UncategorizedMongoDbException;
|
||||
import org.springframework.data.mongodb.util.MongoDbErrorCodes;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import com.mongodb.BulkWriteException;
|
||||
import com.mongodb.MongoException;
|
||||
|
||||
/**
|
||||
@@ -46,12 +42,12 @@ import com.mongodb.MongoException;
|
||||
*/
|
||||
public class MongoExceptionTranslator implements PersistenceExceptionTranslator {
|
||||
|
||||
private static final Set<String> DULICATE_KEY_EXCEPTIONS = new HashSet<String>(
|
||||
Arrays.asList("MongoException.DuplicateKey", "DuplicateKeyException"));
|
||||
private static final Set<String> DULICATE_KEY_EXCEPTIONS = new HashSet<String>(Arrays.asList(
|
||||
"MongoException.DuplicateKey", "DuplicateKeyException"));
|
||||
|
||||
private static final Set<String> RESOURCE_FAILURE_EXCEPTIONS = new HashSet<String>(
|
||||
Arrays.asList("MongoException.Network", "MongoSocketException", "MongoException.CursorNotFound",
|
||||
"MongoCursorNotFoundException", "MongoServerSelectionException", "MongoTimeoutException"));
|
||||
private static final Set<String> RESOURCE_FAILURE_EXCEPTIONS = new HashSet<String>(Arrays.asList(
|
||||
"MongoException.Network", "MongoSocketException", "MongoException.CursorNotFound",
|
||||
"MongoCursorNotFoundException", "MongoServerSelectionException", "MongoTimeoutException"));
|
||||
|
||||
private static final Set<String> RESOURCE_USAGE_EXCEPTIONS = new HashSet<String>(
|
||||
Arrays.asList("MongoInternalException"));
|
||||
@@ -85,24 +81,17 @@ public class MongoExceptionTranslator implements PersistenceExceptionTranslator
|
||||
return new DataIntegrityViolationException(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
if (ex instanceof BulkWriteException) {
|
||||
return new BulkOperationException(ex.getMessage(), (BulkWriteException) ex);
|
||||
}
|
||||
|
||||
// All other MongoExceptions
|
||||
if (ex instanceof MongoException) {
|
||||
|
||||
int code = ((MongoException) ex).getCode();
|
||||
|
||||
if (MongoDbErrorCodes.isDuplicateKeyCode(code)) {
|
||||
if (code == 11000 || code == 11001) {
|
||||
throw new DuplicateKeyException(ex.getMessage(), ex);
|
||||
} else if (MongoDbErrorCodes.isDataAccessResourceFailureCode(code)) {
|
||||
} else if (code == 12000 || code == 13440) {
|
||||
throw new DataAccessResourceFailureException(ex.getMessage(), ex);
|
||||
} else if (MongoDbErrorCodes.isInvalidDataAccessApiUsageCode(code) || code == 10003 || code == 12001
|
||||
|| code == 12010 || code == 12011 || code == 12012) {
|
||||
} else if (code == 10003 || code == 12001 || code == 12010 || code == 12011 || code == 12012) {
|
||||
throw new InvalidDataAccessApiUsageException(ex.getMessage(), ex);
|
||||
} else if (MongoDbErrorCodes.isPermissionDeniedCode(code)) {
|
||||
throw new PermissionDeniedDataAccessException(ex.getMessage(), ex);
|
||||
}
|
||||
return new UncategorizedMongoDbException(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.data.geo.GeoResults;
|
||||
import org.springframework.data.mongodb.core.BulkOperations.BulkMode;
|
||||
import org.springframework.data.mongodb.core.aggregation.Aggregation;
|
||||
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
|
||||
import org.springframework.data.mongodb.core.aggregation.TypedAggregation;
|
||||
@@ -293,34 +292,6 @@ public interface MongoOperations {
|
||||
*/
|
||||
ScriptOperations scriptOps();
|
||||
|
||||
/**
|
||||
* Returns a new {@link BulkOperations} for the given collection.
|
||||
*
|
||||
* @param mode the {@link BulkMode} to use for bulk operations, must not be {@literal null}.
|
||||
* @param collectionName the name of the collection to work on, must not be {@literal null} or empty.
|
||||
* @return {@link BulkOperations} on the named collection
|
||||
*/
|
||||
BulkOperations bulkOps(BulkMode mode, String collectionName);
|
||||
|
||||
/**
|
||||
* Returns a new {@link BulkOperations} for the given entity type.
|
||||
*
|
||||
* @param mode the {@link BulkMode} to use for bulk operations, must not be {@literal null}.
|
||||
* @param entityType the name of the entity class, must not be {@literal null}.
|
||||
* @return {@link BulkOperations} on the named collection associated of the given entity class.
|
||||
*/
|
||||
BulkOperations bulkOps(BulkMode mode, Class<?> entityType);
|
||||
|
||||
/**
|
||||
* Returns a new {@link BulkOperations} for the given entity type and collection name.
|
||||
*
|
||||
* @param mode the {@link BulkMode} to use for bulk operations, must not be {@literal null}.
|
||||
* @param entityClass the name of the entity class, must not be {@literal null}.
|
||||
* @param collectionName the name of the collection to work on, must not be {@literal null} or empty.
|
||||
* @return {@link BulkOperations} on the named collection associated with the given entity class.
|
||||
*/
|
||||
BulkOperations bulkOps(BulkMode mode, Class<?> entityType, String collectionName);
|
||||
|
||||
/**
|
||||
* Query for a list of objects of type T from the collection used by the entity class.
|
||||
* <p/>
|
||||
@@ -629,8 +600,8 @@ public interface MongoOperations {
|
||||
<T> T findById(Object id, Class<T> entityClass, String collectionName);
|
||||
|
||||
/**
|
||||
* Triggers <a href="http://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify
|
||||
* <a/> to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query}.
|
||||
* Triggers <a href="http://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify<a/>
|
||||
* to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query}.
|
||||
*
|
||||
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a record and also an optional
|
||||
* fields specification.
|
||||
@@ -641,8 +612,8 @@ public interface MongoOperations {
|
||||
<T> T findAndModify(Query query, Update update, Class<T> entityClass);
|
||||
|
||||
/**
|
||||
* Triggers <a href="http://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify
|
||||
* <a/> to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query}.
|
||||
* Triggers <a href="http://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify<a/>
|
||||
* to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query}.
|
||||
*
|
||||
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a record and also an optional
|
||||
* fields specification.
|
||||
@@ -654,8 +625,8 @@ public interface MongoOperations {
|
||||
<T> T findAndModify(Query query, Update update, Class<T> entityClass, String collectionName);
|
||||
|
||||
/**
|
||||
* Triggers <a href="http://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify
|
||||
* <a/> to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query} taking
|
||||
* Triggers <a href="http://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify<a/>
|
||||
* to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query} taking
|
||||
* {@link FindAndModifyOptions} into account.
|
||||
*
|
||||
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a record and also an optional
|
||||
@@ -668,8 +639,8 @@ public interface MongoOperations {
|
||||
<T> T findAndModify(Query query, Update update, FindAndModifyOptions options, Class<T> entityClass);
|
||||
|
||||
/**
|
||||
* Triggers <a href="http://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify
|
||||
* <a/> to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query} taking
|
||||
* Triggers <a href="http://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify<a/>
|
||||
* to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query} taking
|
||||
* {@link FindAndModifyOptions} into account.
|
||||
*
|
||||
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a record and also an optional
|
||||
@@ -757,9 +728,9 @@ public interface MongoOperations {
|
||||
* <p/>
|
||||
* If you object has an "Id' property, it will be set with the generated Id from MongoDB. If your Id property is a
|
||||
* String then MongoDB ObjectId will be used to populate that string. Otherwise, the conversion from ObjectId to your
|
||||
* property type will be handled by Spring's BeanWrapper class that leverages Type Conversion API. See
|
||||
* <a href="http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html#core-convert" >
|
||||
* Spring's Type Conversion"</a> for more details.
|
||||
* property type will be handled by Spring's BeanWrapper class that leverages Type Conversion API. See <a
|
||||
* href="http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html#core-convert"
|
||||
* >Spring's Type Conversion"</a> for more details.
|
||||
* <p/>
|
||||
* <p/>
|
||||
* Insert is used to initially store the object into the database. To update an existing object use the save method.
|
||||
@@ -814,9 +785,9 @@ public interface MongoOperations {
|
||||
* <p/>
|
||||
* If you object has an "Id' property, it will be set with the generated Id from MongoDB. If your Id property is a
|
||||
* String then MongoDB ObjectId will be used to populate that string. Otherwise, the conversion from ObjectId to your
|
||||
* property type will be handled by Spring's BeanWrapper class that leverages Type Conversion API. See
|
||||
* <a href="http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html#core-convert" >
|
||||
* Spring's Type Conversion"</a> for more details.
|
||||
* property type will be handled by Spring's BeanWrapper class that leverages Type Conversion API. See <a
|
||||
* href="http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html#core-convert"
|
||||
* >Spring's Type Conversion"</a> for more details.
|
||||
*
|
||||
* @param objectToSave the object to store in the collection
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2015 the original author or authors.
|
||||
* Copyright 2010-2016 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.
|
||||
@@ -60,7 +60,6 @@ import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mapping.model.ConvertingPropertyAccessor;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.mongodb.MongoDbFactory;
|
||||
import org.springframework.data.mongodb.core.BulkOperations.BulkMode;
|
||||
import org.springframework.data.mongodb.core.aggregation.Aggregation;
|
||||
import org.springframework.data.mongodb.core.aggregation.AggregationOperationContext;
|
||||
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
|
||||
@@ -138,6 +137,7 @@ import com.mongodb.util.JSONParseException;
|
||||
* @author Chuong Ngo
|
||||
* @author Christoph Strobl
|
||||
* @author Doménique Tilleuil
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
@@ -339,8 +339,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
DBCursor cursor = collection.find(mappedQuery, mappedFields);
|
||||
QueryCursorPreparer cursorPreparer = new QueryCursorPreparer(query, entityType);
|
||||
|
||||
ReadDbObjectCallback<T> readCallback = new ReadDbObjectCallback<T>(mongoConverter, entityType,
|
||||
collection.getName());
|
||||
ReadDbObjectCallback<T> readCallback = new ReadDbObjectCallback<T>(mongoConverter, entityType);
|
||||
|
||||
return new CloseableIterableCursorAdapter<T>(cursorPreparer.prepare(cursor), exceptionTranslator, readCallback);
|
||||
}
|
||||
@@ -373,8 +372,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
*/
|
||||
@Deprecated
|
||||
public CommandResult executeCommand(final DBObject command, final int options) {
|
||||
return executeCommand(command,
|
||||
(options & Bytes.QUERYOPTION_SLAVEOK) != 0 ? ReadPreference.secondaryPreferred() : ReadPreference.primary());
|
||||
return executeCommand(command, (options & Bytes.QUERYOPTION_SLAVEOK) != 0 ? ReadPreference.secondaryPreferred()
|
||||
: ReadPreference.primary());
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -397,13 +396,11 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
|
||||
protected void logCommandExecutionError(final DBObject command, CommandResult result) {
|
||||
|
||||
String error = result.getErrorMessage();
|
||||
|
||||
if (error != null) {
|
||||
// TODO: DATADOC-204 allow configuration of logging level / throw
|
||||
// throw new
|
||||
// InvalidDataAccessApiUsageException("Command execution of " +
|
||||
// command.toString() + " failed: " + error);
|
||||
LOGGER.warn("Command execution of " + command.toString() + " failed: " + error);
|
||||
LOGGER.warn("Command execution of {} failed: {}", command.toString(), error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -422,8 +419,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
* @param preparer allows for customization of the {@link DBCursor} used when iterating over the result set, (apply
|
||||
* limits, skips and so on).
|
||||
*/
|
||||
protected void executeQuery(Query query, String collectionName, DocumentCallbackHandler dch,
|
||||
CursorPreparer preparer) {
|
||||
protected void executeQuery(Query query, String collectionName, DocumentCallbackHandler dch, CursorPreparer preparer) {
|
||||
|
||||
Assert.notNull(query);
|
||||
|
||||
@@ -432,8 +428,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
DBObject fieldsObject = query.getFieldsObject();
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug(String.format("Executing query: %s sort: %s fields: %s in collection: %s",
|
||||
serializeToJsonSafely(queryObject), sortObject, fieldsObject, collectionName));
|
||||
LOGGER.debug("Executing query: {} sort: {} fields: {} in collection: {}", serializeToJsonSafely(queryObject),
|
||||
sortObject, fieldsObject, collectionName);
|
||||
}
|
||||
|
||||
this.executeQueryInternal(new FindCallback(queryObject, fieldsObject), preparer, dch, collectionName);
|
||||
@@ -531,7 +527,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
public Void doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||
collection.drop();
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Dropped collection [" + collection.getFullName() + "]");
|
||||
LOGGER.debug("Dropped collection [{}]", collection.getFullName());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -546,28 +542,6 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
return new DefaultIndexOperations(this, determineCollectionName(entityClass));
|
||||
}
|
||||
|
||||
public BulkOperations bulkOps(BulkMode bulkMode, String collectionName) {
|
||||
return bulkOps(bulkMode, null, collectionName);
|
||||
}
|
||||
|
||||
public BulkOperations bulkOps(BulkMode bulkMode, Class<?> entityClass) {
|
||||
return bulkOps(bulkMode, entityClass, determineCollectionName(entityClass));
|
||||
}
|
||||
|
||||
public BulkOperations bulkOps(BulkMode mode, Class<?> entityType, String collectionName) {
|
||||
|
||||
Assert.notNull(mode, "BulkMode must not be null!");
|
||||
Assert.hasText(collectionName, "Collection name must not be null or empty!");
|
||||
|
||||
DefaultBulkOperations operations = new DefaultBulkOperations(this, mode, collectionName, entityType);
|
||||
|
||||
operations.setExceptionTranslator(exceptionTranslator);
|
||||
operations.setWriteConcernResolver(writeConcernResolver);
|
||||
operations.setDefaultWriteConcern(writeConcern);
|
||||
|
||||
return operations;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.MongoOperations#scriptOps()
|
||||
@@ -664,12 +638,17 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
command.put("query", queryMapper.getMappedObject(query, getPersistentEntity(entityClass)));
|
||||
}
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Executing geoNear using: {} for class: {} in collection: {}", serializeToJsonSafely(command),
|
||||
entityClass, collectionName);
|
||||
}
|
||||
|
||||
CommandResult commandResult = executeCommand(command, this.readPreference);
|
||||
List<Object> results = (List<Object>) commandResult.get("results");
|
||||
results = results == null ? Collections.emptyList() : results;
|
||||
|
||||
DbObjectCallback<GeoResult<T>> callback = new GeoNearResultDbObjectCallback<T>(
|
||||
new ReadDbObjectCallback<T>(mongoConverter, entityClass, collectionName), near.getMetric());
|
||||
DbObjectCallback<GeoResult<T>> callback = new GeoNearResultDbObjectCallback<T>(new ReadDbObjectCallback<T>(
|
||||
mongoConverter, entityClass), near.getMetric());
|
||||
List<GeoResult<T>> result = new ArrayList<GeoResult<T>>(results.size());
|
||||
|
||||
int index = 0;
|
||||
@@ -745,9 +724,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
public long count(Query query, Class<?> entityClass, String collectionName) {
|
||||
|
||||
Assert.hasText(collectionName);
|
||||
final DBObject dbObject = query == null ? null
|
||||
: queryMapper.getMappedObject(query.getQueryObject(),
|
||||
entityClass == null ? null : mappingContext.getPersistentEntity(entityClass));
|
||||
final DBObject dbObject = query == null ? null : queryMapper.getMappedObject(query.getQueryObject(),
|
||||
entityClass == null ? null : mappingContext.getPersistentEntity(entityClass));
|
||||
|
||||
return execute(collectionName, new CollectionCallback<Long>() {
|
||||
public Long doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||
@@ -827,15 +805,15 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
initializeVersionProperty(objectToSave);
|
||||
|
||||
maybeEmitEvent(new BeforeConvertEvent<T>(objectToSave, collectionName));
|
||||
maybeEmitEvent(new BeforeConvertEvent<T>(objectToSave));
|
||||
|
||||
DBObject dbDoc = toDbObject(objectToSave, writer);
|
||||
|
||||
maybeEmitEvent(new BeforeSaveEvent<T>(objectToSave, dbDoc, collectionName));
|
||||
maybeEmitEvent(new BeforeSaveEvent<T>(objectToSave, dbDoc));
|
||||
Object id = insertDBObject(collectionName, dbDoc, objectToSave.getClass());
|
||||
|
||||
populateIdIfNecessary(objectToSave, id);
|
||||
maybeEmitEvent(new AfterSaveEvent<T>(objectToSave, dbDoc, collectionName));
|
||||
maybeEmitEvent(new AfterSaveEvent<T>(objectToSave, dbDoc));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -923,10 +901,10 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
initializeVersionProperty(o);
|
||||
BasicDBObject dbDoc = new BasicDBObject();
|
||||
|
||||
maybeEmitEvent(new BeforeConvertEvent<T>(o, collectionName));
|
||||
maybeEmitEvent(new BeforeConvertEvent<T>(o));
|
||||
writer.write(o, dbDoc);
|
||||
|
||||
maybeEmitEvent(new BeforeSaveEvent<T>(o, dbDoc, collectionName));
|
||||
maybeEmitEvent(new BeforeSaveEvent<T>(o, dbDoc));
|
||||
dbObjectList.add(dbDoc);
|
||||
}
|
||||
List<ObjectId> ids = insertDBObjectList(collectionName, dbObjectList);
|
||||
@@ -934,7 +912,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
for (T obj : batchToSave) {
|
||||
if (i < ids.size()) {
|
||||
populateIdIfNecessary(obj, ids.get(i));
|
||||
maybeEmitEvent(new AfterSaveEvent<T>(obj, dbObjectList.get(i), collectionName));
|
||||
maybeEmitEvent(new AfterSaveEvent<T>(obj, dbObjectList.get(i)));
|
||||
}
|
||||
i++;
|
||||
}
|
||||
@@ -989,14 +967,14 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
BasicDBObject dbObject = new BasicDBObject();
|
||||
|
||||
maybeEmitEvent(new BeforeConvertEvent<T>(objectToSave, collectionName));
|
||||
maybeEmitEvent(new BeforeConvertEvent<T>(objectToSave));
|
||||
this.mongoConverter.write(objectToSave, dbObject);
|
||||
|
||||
maybeEmitEvent(new BeforeSaveEvent<T>(objectToSave, dbObject, collectionName));
|
||||
maybeEmitEvent(new BeforeSaveEvent<T>(objectToSave, dbObject));
|
||||
Update update = Update.fromDBObject(dbObject, ID_FIELD);
|
||||
|
||||
doUpdate(collectionName, query, update, objectToSave.getClass(), false, false);
|
||||
maybeEmitEvent(new AfterSaveEvent<T>(objectToSave, dbObject, collectionName));
|
||||
maybeEmitEvent(new AfterSaveEvent<T>(objectToSave, dbObject));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1004,28 +982,30 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
assertUpdateableIdIfNotSet(objectToSave);
|
||||
|
||||
maybeEmitEvent(new BeforeConvertEvent<T>(objectToSave, collectionName));
|
||||
maybeEmitEvent(new BeforeConvertEvent<T>(objectToSave));
|
||||
|
||||
DBObject dbDoc = toDbObject(objectToSave, writer);
|
||||
|
||||
maybeEmitEvent(new BeforeSaveEvent<T>(objectToSave, dbDoc, collectionName));
|
||||
maybeEmitEvent(new BeforeSaveEvent<T>(objectToSave, dbDoc));
|
||||
Object id = saveDBObject(collectionName, dbDoc, objectToSave.getClass());
|
||||
|
||||
populateIdIfNecessary(objectToSave, id);
|
||||
maybeEmitEvent(new AfterSaveEvent<T>(objectToSave, dbDoc, collectionName));
|
||||
maybeEmitEvent(new AfterSaveEvent<T>(objectToSave, dbDoc));
|
||||
}
|
||||
|
||||
protected Object insertDBObject(final String collectionName, final DBObject dbDoc, final Class<?> entityClass) {
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Inserting DBObject containing fields: " + dbDoc.keySet() + " in collection: " + collectionName);
|
||||
LOGGER.debug("Inserting DBObject containing fields: {} in collection: {}", dbDoc.keySet(), 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 writeResult = writeConcernToUse == null ? collection.insert(dbDoc)
|
||||
: collection.insert(dbDoc, writeConcernToUse);
|
||||
WriteResult writeResult = writeConcernToUse == null ? collection.insert(dbDoc) : collection.insert(dbDoc,
|
||||
writeConcernToUse);
|
||||
handleAnyWriteResultErrors(writeResult, dbDoc, MongoActionOperation.INSERT);
|
||||
return dbDoc.get(ID_FIELD);
|
||||
}
|
||||
@@ -1038,15 +1018,16 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Inserting list of DBObjects containing " + dbDocList.size() + " items");
|
||||
LOGGER.debug("Inserting list of DBObjects containing {} items", dbDocList.size());
|
||||
}
|
||||
|
||||
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 writeResult = writeConcernToUse == null ? collection.insert(dbDocList)
|
||||
: collection.insert(dbDocList.toArray((DBObject[]) new BasicDBObject[dbDocList.size()]), writeConcernToUse);
|
||||
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;
|
||||
}
|
||||
@@ -1066,16 +1047,18 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
|
||||
protected Object saveDBObject(final String collectionName, final DBObject dbDoc, final Class<?> entityClass) {
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Saving 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 writeResult = writeConcernToUse == null ? collection.save(dbDoc)
|
||||
: collection.save(dbDoc, writeConcernToUse);
|
||||
WriteResult writeResult = writeConcernToUse == null ? collection.save(dbDoc) : collection.save(dbDoc,
|
||||
writeConcernToUse);
|
||||
handleAnyWriteResultErrors(writeResult, dbDoc, MongoActionOperation.SAVE);
|
||||
return dbDoc.get(ID_FIELD);
|
||||
}
|
||||
@@ -1128,14 +1111,14 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
increaseVersionForUpdateIfNecessary(entity, update);
|
||||
|
||||
DBObject queryObj = query == null ? new BasicDBObject()
|
||||
: queryMapper.getMappedObject(query.getQueryObject(), entity);
|
||||
DBObject updateObj = update == null ? new BasicDBObject()
|
||||
: updateMapper.getMappedObject(update.getUpdateObject(), entity);
|
||||
DBObject queryObj = query == null ? new BasicDBObject() : queryMapper.getMappedObject(query.getQueryObject(),
|
||||
entity);
|
||||
DBObject updateObj = update == null ? new BasicDBObject() : updateMapper.getMappedObject(
|
||||
update.getUpdateObject(), entity);
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug(String.format("Calling update using query: %s and update: %s in collection: %s",
|
||||
serializeToJsonSafely(queryObj), serializeToJsonSafely(updateObj), collectionName));
|
||||
LOGGER.debug("Calling update using query: {} and update: {} in collection: {}",
|
||||
serializeToJsonSafely(queryObj), serializeToJsonSafely(updateObj), collectionName);
|
||||
}
|
||||
|
||||
MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.UPDATE, collectionName,
|
||||
@@ -1272,9 +1255,9 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
Object idValue = persistentEntity.getPropertyAccessor(entity).getProperty(idProperty);
|
||||
|
||||
if (idValue == null && !MongoSimpleTypes.AUTOGENERATED_ID_TYPES.contains(idProperty.getType())) {
|
||||
throw new InvalidDataAccessApiUsageException(
|
||||
String.format("Cannot autogenerate id of type %s for entity of type %s!", idProperty.getType().getName(),
|
||||
entity.getClass().getName()));
|
||||
throw new InvalidDataAccessApiUsageException(String.format(
|
||||
"Cannot autogenerate id of type %s for entity of type %s!", idProperty.getType().getName(), entity.getClass()
|
||||
.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1304,7 +1287,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
return execute(collectionName, new CollectionCallback<WriteResult>() {
|
||||
public WriteResult doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||
|
||||
maybeEmitEvent(new BeforeDeleteEvent<T>(queryObject, entityClass, collectionName));
|
||||
maybeEmitEvent(new BeforeDeleteEvent<T>(queryObject, entityClass));
|
||||
|
||||
DBObject dboq = queryMapper.getMappedObject(queryObject, entity);
|
||||
|
||||
@@ -1313,16 +1296,16 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction);
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Remove using query: {} in collection: {}.",
|
||||
new Object[] { serializeToJsonSafely(dboq), collection.getName() });
|
||||
LOGGER.debug("Remove using query: {} in collection: {}.", new Object[] { serializeToJsonSafely(dboq),
|
||||
collection.getName() });
|
||||
}
|
||||
|
||||
WriteResult wr = writeConcernToUse == null ? collection.remove(dboq)
|
||||
: collection.remove(dboq, writeConcernToUse);
|
||||
WriteResult wr = writeConcernToUse == null ? collection.remove(dboq) : collection.remove(dboq,
|
||||
writeConcernToUse);
|
||||
|
||||
handleAnyWriteResultErrors(wr, dboq, MongoActionOperation.REMOVE);
|
||||
|
||||
maybeEmitEvent(new AfterDeleteEvent<T>(queryObject, entityClass, collectionName));
|
||||
maybeEmitEvent(new AfterDeleteEvent<T>(queryObject, entityClass));
|
||||
|
||||
return wr;
|
||||
}
|
||||
@@ -1330,12 +1313,13 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
|
||||
public <T> List<T> findAll(Class<T> entityClass) {
|
||||
return findAll(entityClass, determineCollectionName(entityClass));
|
||||
return executeFindMultiInternal(new FindCallback(null), null, new ReadDbObjectCallback<T>(mongoConverter,
|
||||
entityClass), determineCollectionName(entityClass));
|
||||
}
|
||||
|
||||
public <T> List<T> findAll(Class<T> entityClass, String collectionName) {
|
||||
return executeFindMultiInternal(new FindCallback(null), null,
|
||||
new ReadDbObjectCallback<T>(mongoConverter, entityClass, collectionName), collectionName);
|
||||
return executeFindMultiInternal(new FindCallback(null), null, new ReadDbObjectCallback<T>(mongoConverter,
|
||||
entityClass), collectionName);
|
||||
}
|
||||
|
||||
public <T> MapReduceResults<T> mapReduce(String inputCollectionName, String mapFunction, String reduceFunction,
|
||||
@@ -1351,8 +1335,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
public <T> MapReduceResults<T> mapReduce(Query query, String inputCollectionName, String mapFunction,
|
||||
String reduceFunction, Class<T> entityClass) {
|
||||
return mapReduce(query, inputCollectionName, mapFunction, reduceFunction, new MapReduceOptions().outputTypeInline(),
|
||||
entityClass);
|
||||
return mapReduce(query, inputCollectionName, mapFunction, reduceFunction,
|
||||
new MapReduceOptions().outputTypeInline(), entityClass);
|
||||
}
|
||||
|
||||
public <T> MapReduceResults<T> mapReduce(Query query, String inputCollectionName, String mapFunction,
|
||||
@@ -1363,15 +1347,14 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
DBCollection inputCollection = getCollection(inputCollectionName);
|
||||
|
||||
MapReduceCommand command = new MapReduceCommand(inputCollection, mapFunc, reduceFunc,
|
||||
mapReduceOptions.getOutputCollection(), mapReduceOptions.getOutputType(),
|
||||
query == null || query.getQueryObject() == null ? null
|
||||
: queryMapper.getMappedObject(query.getQueryObject(), null));
|
||||
mapReduceOptions.getOutputCollection(), mapReduceOptions.getOutputType(), query == null
|
||||
|| query.getQueryObject() == null ? null : queryMapper.getMappedObject(query.getQueryObject(), null));
|
||||
|
||||
copyMapReduceOptionsToCommand(query, mapReduceOptions, command);
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Executing MapReduce on collection [" + command.getInput() + "], mapFunction [" + mapFunc
|
||||
+ "], reduceFunction [" + reduceFunc + "]");
|
||||
LOGGER.debug("Executing MapReduce on collection [{}], mapFunction [{}], reduceFunction [{}]", command.getInput(),
|
||||
mapFunc, reduceFunc);
|
||||
}
|
||||
|
||||
MapReduceOutput mapReduceOutput = inputCollection.mapReduce(command);
|
||||
@@ -1381,7 +1364,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
|
||||
List<T> mappedResults = new ArrayList<T>();
|
||||
DbObjectCallback<T> callback = new ReadDbObjectCallback<T>(mongoConverter, entityClass, inputCollectionName);
|
||||
DbObjectCallback<T> callback = new ReadDbObjectCallback<T>(mongoConverter, entityClass);
|
||||
|
||||
for (DBObject dbObject : mapReduceOutput.results()) {
|
||||
mappedResults.add(callback.doWith(dbObject));
|
||||
@@ -1442,7 +1425,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
@SuppressWarnings("unchecked")
|
||||
Iterable<DBObject> resultSet = (Iterable<DBObject>) commandResult.get("retval");
|
||||
List<T> mappedResults = new ArrayList<T>();
|
||||
DbObjectCallback<T> callback = new ReadDbObjectCallback<T>(mongoConverter, entityClass, inputCollectionName);
|
||||
DbObjectCallback<T> callback = new ReadDbObjectCallback<T>(mongoConverter, entityClass);
|
||||
|
||||
for (DBObject dbObject : resultSet) {
|
||||
mappedResults.add(callback.doWith(dbObject));
|
||||
@@ -1544,8 +1527,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
CommandResult commandResult = executeCommand(command, this.readPreference);
|
||||
handleCommandError(commandResult, command);
|
||||
|
||||
return new AggregationResults<O>(returnPotentiallyMappedResults(outputType, commandResult, collectionName),
|
||||
commandResult);
|
||||
return new AggregationResults<O>(returnPotentiallyMappedResults(outputType, commandResult), commandResult);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1555,8 +1537,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
* @param commandResult
|
||||
* @return
|
||||
*/
|
||||
private <O> List<O> returnPotentiallyMappedResults(Class<O> outputType, CommandResult commandResult,
|
||||
String collectionName) {
|
||||
private <O> List<O> returnPotentiallyMappedResults(Class<O> outputType, CommandResult commandResult) {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Iterable<DBObject> resultSet = (Iterable<DBObject>) commandResult.get("result");
|
||||
@@ -1564,7 +1545,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
DbObjectCallback<O> callback = new UnwrapAndReadDbObjectCallback<O>(mongoConverter, outputType, collectionName);
|
||||
DbObjectCallback<O> callback = new UnwrapAndReadDbObjectCallback<O>(mongoConverter, outputType);
|
||||
|
||||
List<O> mappedResults = new ArrayList<O>();
|
||||
for (DBObject dbObject : resultSet) {
|
||||
@@ -1697,12 +1678,12 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
DBObject mappedFields = fields == null ? null : queryMapper.getMappedObject(fields, entity);
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug(String.format("findOne using query: %s fields: %s for class: %s in collection: %s",
|
||||
serializeToJsonSafely(query), mappedFields, entityClass, collectionName));
|
||||
LOGGER.debug("findOne using query: {} fields: {} for class: {} in collection: {}", serializeToJsonSafely(query),
|
||||
mappedFields, entityClass, collectionName);
|
||||
}
|
||||
|
||||
return executeFindOneInternal(new FindOneCallback(mappedQuery, mappedFields),
|
||||
new ReadDbObjectCallback<T>(this.mongoConverter, entityClass, collectionName), collectionName);
|
||||
return executeFindOneInternal(new FindOneCallback(mappedQuery, mappedFields), new ReadDbObjectCallback<T>(
|
||||
this.mongoConverter, entityClass), collectionName);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1716,8 +1697,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
* @return the List of converted objects.
|
||||
*/
|
||||
protected <T> List<T> doFind(String collectionName, DBObject query, DBObject fields, Class<T> entityClass) {
|
||||
return doFind(collectionName, query, fields, entityClass, null,
|
||||
new ReadDbObjectCallback<T>(this.mongoConverter, entityClass, collectionName));
|
||||
return doFind(collectionName, query, fields, entityClass, null, new ReadDbObjectCallback<T>(this.mongoConverter,
|
||||
entityClass));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1735,8 +1716,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
*/
|
||||
protected <T> List<T> doFind(String collectionName, DBObject query, DBObject fields, Class<T> entityClass,
|
||||
CursorPreparer preparer) {
|
||||
return doFind(collectionName, query, fields, entityClass, preparer,
|
||||
new ReadDbObjectCallback<T>(mongoConverter, entityClass, collectionName));
|
||||
return doFind(collectionName, query, fields, entityClass, preparer, new ReadDbObjectCallback<T>(mongoConverter,
|
||||
entityClass));
|
||||
}
|
||||
|
||||
protected <S, T> List<T> doFind(String collectionName, DBObject query, DBObject fields, Class<S> entityClass,
|
||||
@@ -1748,8 +1729,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
DBObject mappedQuery = queryMapper.getMappedObject(query, entity);
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug(String.format("find using query: %s fields: %s for class: %s in collection: %s",
|
||||
serializeToJsonSafely(mappedQuery), mappedFields, entityClass, collectionName));
|
||||
LOGGER.debug("find using query: {} fields: {} for class: {} in collection: {}",
|
||||
serializeToJsonSafely(mappedQuery), mappedFields, entityClass, collectionName);
|
||||
}
|
||||
|
||||
return executeFindMultiInternal(new FindCallback(mappedQuery, mappedFields), preparer, objectCallback,
|
||||
@@ -1785,14 +1766,18 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
*/
|
||||
protected <T> T doFindAndRemove(String collectionName, DBObject query, DBObject fields, DBObject sort,
|
||||
Class<T> entityClass) {
|
||||
|
||||
EntityReader<? super T, DBObject> readerToUse = this.mongoConverter;
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug(String.format("findAndRemove using query: %s fields: %s sort: %s for class: %s in collection: %s",
|
||||
serializeToJsonSafely(query), fields, sort, entityClass, collectionName));
|
||||
LOGGER.debug("findAndRemove using query: {} fields: {} sort: {} for class: {} in collection: {}",
|
||||
serializeToJsonSafely(query), fields, sort, entityClass, collectionName);
|
||||
}
|
||||
|
||||
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass);
|
||||
|
||||
return executeFindOneInternal(new FindAndRemoveCallback(queryMapper.getMappedObject(query, entity), fields, sort),
|
||||
new ReadDbObjectCallback<T>(readerToUse, entityClass, collectionName), collectionName);
|
||||
new ReadDbObjectCallback<T>(readerToUse, entityClass), collectionName);
|
||||
}
|
||||
|
||||
protected <T> T doFindAndModify(String collectionName, DBObject query, DBObject fields, DBObject sort,
|
||||
@@ -1812,17 +1797,14 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
DBObject mappedUpdate = updateMapper.getMappedObject(update.getUpdateObject(), entity);
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER
|
||||
.debug(
|
||||
String.format(
|
||||
"findAndModify using query: %s fields: %s sort: %s for class: %s and update: %s "
|
||||
+ "in collection: %s",
|
||||
serializeToJsonSafely(mappedQuery), fields, sort, entityClass, serializeToJsonSafely(mappedUpdate),
|
||||
collectionName));
|
||||
LOGGER.debug(
|
||||
"findAndModify using query: {} fields: {} sort: {} for class: {} and update: {} " + "in collection: {}",
|
||||
serializeToJsonSafely(mappedQuery), fields, sort, entityClass, serializeToJsonSafely(mappedUpdate),
|
||||
collectionName);
|
||||
}
|
||||
|
||||
return executeFindOneInternal(new FindAndModifyCallback(mappedQuery, fields, sort, mappedUpdate, options),
|
||||
new ReadDbObjectCallback<T>(readerToUse, entityClass, collectionName), collectionName);
|
||||
new ReadDbObjectCallback<T>(readerToUse, entityClass), collectionName);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1888,8 +1870,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
DbObjectCallback<T> objectCallback, String collectionName) {
|
||||
|
||||
try {
|
||||
T result = objectCallback
|
||||
.doWith(collectionCallback.doInCollection(getAndPrepareCollection(getDb(), collectionName)));
|
||||
T result = objectCallback.doWith(collectionCallback.doInCollection(getAndPrepareCollection(getDb(),
|
||||
collectionName)));
|
||||
return result;
|
||||
} catch (RuntimeException e) {
|
||||
throw potentiallyConvertRuntimeException(e, exceptionTranslator);
|
||||
@@ -1914,8 +1896,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
* @param collectionName the collection to be queried
|
||||
* @return
|
||||
*/
|
||||
private <T> List<T> executeFindMultiInternal(CollectionCallback<DBCursor> collectionCallback, CursorPreparer preparer,
|
||||
DbObjectCallback<T> objectCallback, String collectionName) {
|
||||
private <T> List<T> executeFindMultiInternal(CollectionCallback<DBCursor> collectionCallback,
|
||||
CursorPreparer preparer, DbObjectCallback<T> objectCallback, String collectionName) {
|
||||
|
||||
try {
|
||||
|
||||
@@ -2005,8 +1987,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass);
|
||||
if (entity == null) {
|
||||
throw new InvalidDataAccessApiUsageException(
|
||||
"No Persistent Entity information found for the class " + entityClass.getName());
|
||||
throw new InvalidDataAccessApiUsageException("No Persitent Entity information found for the class "
|
||||
+ entityClass.getName());
|
||||
}
|
||||
return entity.getCollection();
|
||||
}
|
||||
@@ -2070,8 +2052,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
String error = result.getErrorMessage();
|
||||
error = error == null ? "NO MESSAGE" : error;
|
||||
|
||||
throw new InvalidDataAccessApiUsageException(
|
||||
"Command execution failed: Error [" + error + "], Command = " + source, ex);
|
||||
throw new InvalidDataAccessApiUsageException("Command execution failed: Error [" + error + "], Command = "
|
||||
+ source, ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2128,14 +2110,14 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
public DBObject doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||
if (fields == null) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug(String.format("findOne using query: %s in db.collection: %s", serializeToJsonSafely(query),
|
||||
collection.getFullName()));
|
||||
LOGGER.debug("findOne using query: {} in db.collection: {}", serializeToJsonSafely(query),
|
||||
collection.getFullName());
|
||||
}
|
||||
return collection.findOne(query);
|
||||
} else {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug(String.format("findOne using query: %s fields: %s in db.collection: %s",
|
||||
serializeToJsonSafely(query), fields, collection.getFullName()));
|
||||
LOGGER.debug("findOne using query: {} fields: {} in db.collection: {}", serializeToJsonSafely(query), fields,
|
||||
collection.getFullName());
|
||||
}
|
||||
return collection.findOne(query, fields);
|
||||
}
|
||||
@@ -2236,30 +2218,26 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
* {@link MongoReader}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
private class ReadDbObjectCallback<T> implements DbObjectCallback<T> {
|
||||
|
||||
private final EntityReader<? super T, DBObject> reader;
|
||||
private final Class<T> type;
|
||||
private final String collectionName;
|
||||
|
||||
public ReadDbObjectCallback(EntityReader<? super T, DBObject> reader, Class<T> type, String collectionName) {
|
||||
|
||||
public ReadDbObjectCallback(EntityReader<? super T, DBObject> reader, Class<T> type) {
|
||||
Assert.notNull(reader);
|
||||
Assert.notNull(type);
|
||||
this.reader = reader;
|
||||
this.type = type;
|
||||
this.collectionName = collectionName;
|
||||
}
|
||||
|
||||
public T doWith(DBObject object) {
|
||||
if (null != object) {
|
||||
maybeEmitEvent(new AfterLoadEvent<T>(object, type, collectionName));
|
||||
maybeEmitEvent(new AfterLoadEvent<T>(object, type));
|
||||
}
|
||||
T source = reader.read(type, object);
|
||||
if (null != source) {
|
||||
maybeEmitEvent(new AfterConvertEvent<T>(object, source, collectionName));
|
||||
maybeEmitEvent(new AfterConvertEvent<T>(object, source));
|
||||
}
|
||||
return source;
|
||||
}
|
||||
@@ -2267,9 +2245,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
class UnwrapAndReadDbObjectCallback<T> extends ReadDbObjectCallback<T> {
|
||||
|
||||
public UnwrapAndReadDbObjectCallback(EntityReader<? super T, DBObject> reader, Class<T> type,
|
||||
String collectionName) {
|
||||
super(reader, type, collectionName);
|
||||
public UnwrapAndReadDbObjectCallback(EntityReader<? super T, DBObject> reader, Class<T> type) {
|
||||
super(reader, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -2295,6 +2272,15 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
}
|
||||
|
||||
private enum DefaultWriteConcernResolver implements WriteConcernResolver {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
public WriteConcern resolve(MongoAction action) {
|
||||
return action.getDefaultWriteConcern();
|
||||
}
|
||||
}
|
||||
|
||||
class QueryCursorPreparer implements CursorPreparer {
|
||||
|
||||
private final Query query;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2016 the original author or authors.
|
||||
* Copyright 2011-2015 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.
|
||||
@@ -42,6 +42,16 @@ import org.springframework.data.convert.ReadingConverter;
|
||||
import org.springframework.data.convert.ThreeTenBackPortConverters;
|
||||
import org.springframework.data.convert.WritingConverter;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.BigDecimalToStringConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.BigIntegerToStringConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.DBObjectToNamedMongoScriptCoverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.DBObjectToStringConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.NamedMongoScriptToDBObjectConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.StringToBigDecimalConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.StringToBigIntegerConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.StringToURLConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.TermToStringConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.URLToStringConverter;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoSimpleTypes;
|
||||
import org.springframework.data.util.CacheValue;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -102,7 +112,17 @@ public class CustomConversions {
|
||||
// Add user provided converters to make sure they can override the defaults
|
||||
toRegister.addAll(converters);
|
||||
toRegister.add(CustomToStringConverter.INSTANCE);
|
||||
toRegister.addAll(MongoConverters.getConvertersToRegister());
|
||||
toRegister.add(BigDecimalToStringConverter.INSTANCE);
|
||||
toRegister.add(StringToBigDecimalConverter.INSTANCE);
|
||||
toRegister.add(BigIntegerToStringConverter.INSTANCE);
|
||||
toRegister.add(StringToBigIntegerConverter.INSTANCE);
|
||||
toRegister.add(URLToStringConverter.INSTANCE);
|
||||
toRegister.add(StringToURLConverter.INSTANCE);
|
||||
toRegister.add(DBObjectToStringConverter.INSTANCE);
|
||||
toRegister.add(TermToStringConverter.INSTANCE);
|
||||
toRegister.add(NamedMongoScriptToDBObjectConverter.INSTANCE);
|
||||
toRegister.add(DBObjectToNamedMongoScriptCoverter.INSTANCE);
|
||||
|
||||
toRegister.addAll(JodaTimeConverters.getConvertersToRegister());
|
||||
toRegister.addAll(GeoConverters.getConvertersToRegister());
|
||||
toRegister.addAll(Jsr310Converters.getConvertersToRegister());
|
||||
@@ -166,8 +186,7 @@ public class CustomConversions {
|
||||
}
|
||||
|
||||
if (!added) {
|
||||
throw new IllegalArgumentException(
|
||||
"Given set contains element that is neither Converter nor ConverterFactory!");
|
||||
throw new IllegalArgumentException("Given set contains element that is neither Converter nor ConverterFactory!");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -397,10 +416,6 @@ public class CustomConversions {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.core.convert.converter.GenericConverter#getConvertibleTypes()
|
||||
*/
|
||||
public Set<ConvertiblePair> getConvertibleTypes() {
|
||||
|
||||
ConvertiblePair localeToString = new ConvertiblePair(Locale.class, String.class);
|
||||
@@ -409,10 +424,6 @@ public class CustomConversions {
|
||||
return new HashSet<ConvertiblePair>(Arrays.asList(localeToString, booleanToString));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.core.convert.converter.GenericConverter#convert(java.lang.Object, org.springframework.core.convert.TypeDescriptor, org.springframework.core.convert.TypeDescriptor)
|
||||
*/
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
return source.toString();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2016 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.
|
||||
@@ -45,9 +45,9 @@ import com.mongodb.DBObject;
|
||||
public class DefaultMongoTypeMapper extends DefaultTypeMapper<DBObject> implements MongoTypeMapper {
|
||||
|
||||
public static final String DEFAULT_TYPE_KEY = "_class";
|
||||
@SuppressWarnings("rawtypes") //
|
||||
@SuppressWarnings("rawtypes")//
|
||||
private static final TypeInformation<List> LIST_TYPE_INFO = ClassTypeInformation.from(List.class);
|
||||
@SuppressWarnings("rawtypes") //
|
||||
@SuppressWarnings("rawtypes")//
|
||||
private static final TypeInformation<Map> MAP_TYPE_INFO = ClassTypeInformation.from(Map.class);
|
||||
|
||||
private final TypeAliasAccessor<DBObject> accessor;
|
||||
@@ -58,12 +58,12 @@ public class DefaultMongoTypeMapper extends DefaultTypeMapper<DBObject> implemen
|
||||
}
|
||||
|
||||
public DefaultMongoTypeMapper(String typeKey) {
|
||||
this(typeKey, Arrays.asList(new SimpleTypeInformationMapper()));
|
||||
this(typeKey, Arrays.asList(SimpleTypeInformationMapper.INSTANCE));
|
||||
}
|
||||
|
||||
public DefaultMongoTypeMapper(String typeKey, MappingContext<? extends PersistentEntity<?, ?>, ?> mappingContext) {
|
||||
this(typeKey, new DBObjectTypeAliasAccessor(typeKey), mappingContext,
|
||||
Arrays.asList(new SimpleTypeInformationMapper()));
|
||||
this(typeKey, new DBObjectTypeAliasAccessor(typeKey), mappingContext, Arrays
|
||||
.asList(SimpleTypeInformationMapper.INSTANCE));
|
||||
}
|
||||
|
||||
public DefaultMongoTypeMapper(String typeKey, List<? extends TypeInformationMapper> mappers) {
|
||||
@@ -71,8 +71,7 @@ public class DefaultMongoTypeMapper extends DefaultTypeMapper<DBObject> implemen
|
||||
}
|
||||
|
||||
private DefaultMongoTypeMapper(String typeKey, TypeAliasAccessor<DBObject> accessor,
|
||||
MappingContext<? extends PersistentEntity<?, ?>, ?> mappingContext,
|
||||
List<? extends TypeInformationMapper> mappers) {
|
||||
MappingContext<? extends PersistentEntity<?, ?>, ?> mappingContext, List<? extends TypeInformationMapper> mappers) {
|
||||
|
||||
super(accessor, mappingContext, mappers);
|
||||
|
||||
|
||||
@@ -29,10 +29,10 @@ import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.core.CollectionFactory;
|
||||
import org.springframework.core.convert.ConversionException;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.data.convert.CollectionFactory;
|
||||
import org.springframework.data.convert.EntityInstantiator;
|
||||
import org.springframework.data.convert.TypeMapper;
|
||||
import org.springframework.data.mapping.Association;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2016 the original author or authors.
|
||||
* Copyright 2011-2015 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.
|
||||
@@ -19,26 +19,16 @@ import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Currency;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import org.bson.types.Code;
|
||||
import org.bson.types.ObjectId;
|
||||
import org.springframework.core.convert.ConversionFailedException;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.ConditionalConverter;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.converter.ConverterFactory;
|
||||
import org.springframework.data.convert.ReadingConverter;
|
||||
import org.springframework.data.convert.WritingConverter;
|
||||
import org.springframework.data.mongodb.core.query.Term;
|
||||
import org.springframework.data.mongodb.core.script.NamedMongoScript;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.NumberUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
@@ -59,33 +49,6 @@ abstract class MongoConverters {
|
||||
*/
|
||||
private MongoConverters() {}
|
||||
|
||||
/**
|
||||
* Returns the converters to be registered.
|
||||
*
|
||||
* @return
|
||||
* @since 1.9
|
||||
*/
|
||||
public static Collection<Object> getConvertersToRegister() {
|
||||
|
||||
List<Object> converters = new ArrayList<Object>();
|
||||
|
||||
converters.add(BigDecimalToStringConverter.INSTANCE);
|
||||
converters.add(StringToBigDecimalConverter.INSTANCE);
|
||||
converters.add(BigIntegerToStringConverter.INSTANCE);
|
||||
converters.add(StringToBigIntegerConverter.INSTANCE);
|
||||
converters.add(URLToStringConverter.INSTANCE);
|
||||
converters.add(StringToURLConverter.INSTANCE);
|
||||
converters.add(DBObjectToStringConverter.INSTANCE);
|
||||
converters.add(TermToStringConverter.INSTANCE);
|
||||
converters.add(NamedMongoScriptToDBObjectConverter.INSTANCE);
|
||||
converters.add(DBObjectToNamedMongoScriptCoverter.INSTANCE);
|
||||
converters.add(CurrencyToStringConverter.INSTANCE);
|
||||
converters.add(StringToCurrencyConverter.INSTANCE);
|
||||
converters.add(NumberToNumberConverterFactory.INSTANCE);
|
||||
|
||||
return converters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple singleton to convert {@link ObjectId}s to their {@link String} representation.
|
||||
*
|
||||
@@ -265,113 +228,4 @@ abstract class MongoConverters {
|
||||
return builder.get();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Converter} implementation converting {@link Currency} into its ISO 4217 {@link String} representation.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @since 1.9
|
||||
*/
|
||||
@WritingConverter
|
||||
public static enum CurrencyToStringConverter implements Converter<Currency, String> {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public String convert(Currency source) {
|
||||
return source == null ? null : source.getCurrencyCode();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Converter} implementation converting ISO 4217 {@link String} into {@link Currency}.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @since 1.9
|
||||
*/
|
||||
@ReadingConverter
|
||||
public static enum StringToCurrencyConverter implements Converter<String, Currency> {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public Currency convert(String source) {
|
||||
return StringUtils.hasText(source) ? Currency.getInstance(source) : null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link ConverterFactory} implementation using {@link NumberUtils} for number conversion and parsing. Additionally
|
||||
* deals with {@link AtomicInteger} and {@link AtomicLong} by calling {@code get()} before performing the actual
|
||||
* conversion.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @since 1.9
|
||||
*/
|
||||
@WritingConverter
|
||||
public static enum NumberToNumberConverterFactory implements ConverterFactory<Number, Number>,ConditionalConverter {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.core.convert.converter.ConverterFactory#getConverter(java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
public <T extends Number> Converter<Number, T> getConverter(Class<T> targetType) {
|
||||
return new NumberToNumberConverter<T>(targetType);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.core.convert.converter.ConditionalConverter#matches(org.springframework.core.convert.TypeDescriptor, org.springframework.core.convert.TypeDescriptor)
|
||||
*/
|
||||
@Override
|
||||
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
return !sourceType.equals(targetType);
|
||||
}
|
||||
|
||||
private final static class NumberToNumberConverter<T extends Number> implements Converter<Number, T> {
|
||||
|
||||
private final Class<T> targetType;
|
||||
|
||||
/**
|
||||
* Creates a new {@link NumberToNumberConverter} for the given target type.
|
||||
*
|
||||
* @param targetType must not be {@literal null}.
|
||||
*/
|
||||
public NumberToNumberConverter(Class<T> targetType) {
|
||||
|
||||
Assert.notNull(targetType, "Target type must not be null!");
|
||||
|
||||
this.targetType = targetType;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public T convert(Number source) {
|
||||
|
||||
if (source instanceof AtomicInteger) {
|
||||
return NumberUtils.convertNumberToTargetClass(((AtomicInteger) source).get(), this.targetType);
|
||||
}
|
||||
|
||||
if (source instanceof AtomicLong) {
|
||||
return NumberUtils.convertNumberToTargetClass(((AtomicLong) source).get(), this.targetType);
|
||||
}
|
||||
|
||||
return NumberUtils.convertNumberToTargetClass(source, this.targetType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,7 +226,7 @@ public class QueryMapper {
|
||||
protected DBObject getMappedKeyword(Keyword keyword, MongoPersistentEntity<?> entity) {
|
||||
|
||||
// $or/$nor
|
||||
if (keyword.isOrOrNor() || (keyword.hasIterableValue() && !keyword.isGeometry())) {
|
||||
if (keyword.isOrOrNor() || keyword.hasIterableValue()) {
|
||||
|
||||
Iterable<?> conditions = keyword.getValue();
|
||||
BasicDBList newConditions = new BasicDBList();
|
||||
@@ -556,16 +556,6 @@ public class QueryMapper {
|
||||
return key.matches(N_OR_PATTERN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the current keyword is the {@code $geometry} keyword.
|
||||
*
|
||||
* @return
|
||||
* @since 1.8
|
||||
*/
|
||||
public boolean isGeometry() {
|
||||
return "$geometry".equalsIgnoreCase(key);
|
||||
}
|
||||
|
||||
public boolean hasIterableValue() {
|
||||
return value instanceof Iterable;
|
||||
}
|
||||
|
||||
@@ -29,9 +29,8 @@ import java.lang.annotation.Target;
|
||||
* @author Johno Crawford
|
||||
* @author Thomas Darimont
|
||||
* @author Christoph Strobl
|
||||
* @author Jordi Llach
|
||||
*/
|
||||
@Target({ElementType.ANNOTATION_TYPE, ElementType.FIELD})
|
||||
@Target(ElementType.FIELD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Indexed {
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mapping.context.MappingContextEvent;
|
||||
@@ -30,12 +29,7 @@ import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexRes
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
import org.springframework.data.mongodb.util.MongoDbErrorCodes;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.MongoException;
|
||||
|
||||
/**
|
||||
* Component that inspects {@link MongoPersistentEntity} instances contained in the given {@link MongoMappingContext}
|
||||
@@ -135,34 +129,9 @@ public class MongoPersistentEntityIndexCreator implements ApplicationListener<Ma
|
||||
}
|
||||
}
|
||||
|
||||
void createIndex(IndexDefinitionHolder indexDefinition) {
|
||||
|
||||
try {
|
||||
|
||||
mongoDbFactory.getDb().getCollection(indexDefinition.getCollection()).createIndex(indexDefinition.getIndexKeys(),
|
||||
indexDefinition.getIndexOptions());
|
||||
|
||||
} catch (MongoException ex) {
|
||||
|
||||
if (MongoDbErrorCodes.isDataIntegrityViolationCode(ex.getCode())) {
|
||||
|
||||
DBObject existingIndex = fetchIndexInformation(indexDefinition);
|
||||
String message = "Cannot create index for '%s' in collection '%s' with keys '%s' and options '%s'.";
|
||||
|
||||
if (existingIndex != null) {
|
||||
message += " Index already defined as '%s'.";
|
||||
}
|
||||
|
||||
throw new DataIntegrityViolationException(
|
||||
String.format(message, indexDefinition.getPath(), indexDefinition.getCollection(),
|
||||
indexDefinition.getIndexKeys(), indexDefinition.getIndexOptions(), existingIndex),
|
||||
ex);
|
||||
}
|
||||
|
||||
RuntimeException exceptionToThrow = mongoDbFactory.getExceptionTranslator().translateExceptionIfPossible(ex);
|
||||
|
||||
throw exceptionToThrow != null ? exceptionToThrow : ex;
|
||||
}
|
||||
private void createIndex(IndexDefinitionHolder indexDefinition) {
|
||||
mongoDbFactory.getDb().getCollection(indexDefinition.getCollection()).createIndex(indexDefinition.getIndexKeys(),
|
||||
indexDefinition.getIndexOptions());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -174,28 +143,4 @@ public class MongoPersistentEntityIndexCreator implements ApplicationListener<Ma
|
||||
public boolean isIndexCreatorFor(MappingContext<?, ?> context) {
|
||||
return this.mappingContext.equals(context);
|
||||
}
|
||||
|
||||
private DBObject fetchIndexInformation(IndexDefinitionHolder indexDefinition) {
|
||||
|
||||
if (indexDefinition == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
Object indexNameToLookUp = indexDefinition.getIndexOptions().get("name");
|
||||
|
||||
for (DBObject index : mongoDbFactory.getDb().getCollection(indexDefinition.getCollection()).getIndexInfo()) {
|
||||
if (ObjectUtils.nullSafeEquals(indexNameToLookUp, index.get("name"))) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
LOGGER.debug(
|
||||
String.format("Failed to load index information for collection '%s'.", indexDefinition.getCollection()), e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ 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.core.annotation.AnnotationUtils;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.mapping.Association;
|
||||
import org.springframework.data.mapping.AssociationHandler;
|
||||
@@ -78,7 +77,7 @@ public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T, Mong
|
||||
Class<?> rawType = typeInformation.getType();
|
||||
String fallback = MongoCollectionUtils.getPreferredCollectionName(rawType);
|
||||
|
||||
Document document = AnnotationUtils.findAnnotation(rawType, Document.class);
|
||||
Document document = rawType.getAnnotation(Document.class);
|
||||
|
||||
this.expression = detectExpression(document);
|
||||
this.context = new StandardEvaluationContext();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2015 by the original author(s).
|
||||
* Copyright 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.
|
||||
@@ -21,7 +21,6 @@ import com.mongodb.DBObject;
|
||||
* Base class for delete events.
|
||||
*
|
||||
* @author Martin Baumgartner
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public abstract class AbstractDeleteEvent<T> extends MongoMappingEvent<DBObject> {
|
||||
|
||||
@@ -32,25 +31,11 @@ public abstract class AbstractDeleteEvent<T> extends MongoMappingEvent<DBObject>
|
||||
* Creates a new {@link AbstractDeleteEvent} for the given {@link DBObject} and type.
|
||||
*
|
||||
* @param dbo must not be {@literal null}.
|
||||
* @param type can be {@literal null}.
|
||||
* @deprecated since 1.8. Please use {@link #AbstractDeleteEvent(DBObject, Class, String)}.
|
||||
* @param type , possibly be {@literal null}.
|
||||
*/
|
||||
@Deprecated
|
||||
public AbstractDeleteEvent(DBObject dbo, Class<T> type) {
|
||||
this(dbo, type, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link AbstractDeleteEvent} for the given {@link DBObject} and type.
|
||||
*
|
||||
* @param dbo must not be {@literal null}.
|
||||
* @param type can be {@literal null}.
|
||||
* @param collectionName can be {@literal null}.
|
||||
* @since 1.8
|
||||
*/
|
||||
public AbstractDeleteEvent(DBObject dbo, Class<T> type, String collectionName) {
|
||||
|
||||
super(dbo, dbo, collectionName);
|
||||
super(dbo, dbo);
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2015 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.
|
||||
@@ -28,7 +28,6 @@ import com.mongodb.DBObject;
|
||||
* @author Jon Brisbin
|
||||
* @author Oliver Gierke
|
||||
* @author Martin Baumgartner
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public abstract class AbstractMongoEventListener<E> implements ApplicationListener<MongoMappingEvent<?>> {
|
||||
|
||||
@@ -47,14 +46,14 @@ public abstract class AbstractMongoEventListener<E> implements ApplicationListen
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
|
||||
*/
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@SuppressWarnings("rawtypes")
|
||||
public void onApplicationEvent(MongoMappingEvent<?> event) {
|
||||
|
||||
if (event instanceof AfterLoadEvent) {
|
||||
AfterLoadEvent<?> afterLoadEvent = (AfterLoadEvent<?>) event;
|
||||
|
||||
if (domainClass.isAssignableFrom(afterLoadEvent.getType())) {
|
||||
onAfterLoad((AfterLoadEvent<E>) event);
|
||||
onAfterLoad(event.getDBObject());
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -66,18 +65,18 @@ public abstract class AbstractMongoEventListener<E> implements ApplicationListen
|
||||
|
||||
if (eventDomainType != null && domainClass.isAssignableFrom(eventDomainType)) {
|
||||
if (event instanceof BeforeDeleteEvent) {
|
||||
onBeforeDelete((BeforeDeleteEvent<E>) event);
|
||||
onBeforeDelete(event.getDBObject());
|
||||
}
|
||||
if (event instanceof AfterDeleteEvent) {
|
||||
onAfterDelete((AfterDeleteEvent<E>) event);
|
||||
onAfterDelete(event.getDBObject());
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
Object source = event.getSource();
|
||||
@SuppressWarnings("unchecked")
|
||||
E source = (E) event.getSource();
|
||||
|
||||
// Check for matching domain type and invoke callbacks
|
||||
if (source != null && !domainClass.isAssignableFrom(source.getClass())) {
|
||||
@@ -85,185 +84,55 @@ public abstract class AbstractMongoEventListener<E> implements ApplicationListen
|
||||
}
|
||||
|
||||
if (event instanceof BeforeConvertEvent) {
|
||||
onBeforeConvert((BeforeConvertEvent<E>) event);
|
||||
onBeforeConvert(source);
|
||||
} else if (event instanceof BeforeSaveEvent) {
|
||||
onBeforeSave((BeforeSaveEvent<E>) event);
|
||||
onBeforeSave(source, event.getDBObject());
|
||||
} else if (event instanceof AfterSaveEvent) {
|
||||
onAfterSave((AfterSaveEvent<E>) event);
|
||||
onAfterSave(source, event.getDBObject());
|
||||
} else if (event instanceof AfterConvertEvent) {
|
||||
onAfterConvert((AfterConvertEvent<E>) event);
|
||||
onAfterConvert(event.getDBObject(), source);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures source element before conversion.
|
||||
*
|
||||
* @param source will never be {@literal null}.
|
||||
* @deprecated since 1.8. Please use {@link #onBeforeConvert(BeforeConvertEvent)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public void onBeforeConvert(E source) {
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("onBeforeConvert({})", source);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures {@link BeforeConvertEvent}.
|
||||
*
|
||||
* @param event never {@literal null}.
|
||||
* @since 1.8
|
||||
*/
|
||||
public void onBeforeConvert(BeforeConvertEvent<E> event) {
|
||||
onBeforeConvert(event.getSource());
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures source element and {@link com.mongodb.DBObject} representation before save.
|
||||
*
|
||||
* @param source will never be {@literal null}.
|
||||
* @param dbo can be {@literal null}.
|
||||
* @deprecated since 1.8. Please use {@link #onBeforeSave(BeforeSaveEvent)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public void onBeforeSave(E source, DBObject dbo) {
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("onBeforeSave({}, {})", source, dbo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures {@link BeforeSaveEvent}.
|
||||
*
|
||||
* @param event will never be {@literal null}.
|
||||
* @since 1.8
|
||||
*/
|
||||
public void onBeforeSave(BeforeSaveEvent<E> event) {
|
||||
onBeforeSave(event.getSource(), event.getDBObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures source element and {@link com.mongodb.DBObject} representation after save.
|
||||
*
|
||||
* @param source will never be {@literal null}.
|
||||
* @param dbo can be {@literal null}.
|
||||
* @deprecated since 1.8. Please use {@link #onAfterSave(AfterSaveEvent)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public void onAfterSave(E source, DBObject dbo) {
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("onAfterSave({}, {})", source, dbo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures {@link AfterSaveEvent}.
|
||||
*
|
||||
* @param event will never be {@literal null}.
|
||||
* @since 1.8
|
||||
*/
|
||||
public void onAfterSave(AfterSaveEvent<E> event) {
|
||||
onAfterSave(event.getSource(), event.getDBObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures raw {@link com.mongodb.DBObject} when read from MongoDB.
|
||||
*
|
||||
* @param dbo can be {@literal null}.
|
||||
* @deprecated since 1.8. Please use {@link #onAfterLoad(AfterLoadEvent)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public void onAfterLoad(DBObject dbo) {
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("onAfterLoad({})", dbo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures {@link AfterLoadEvent}.
|
||||
*
|
||||
* @param event will never be {@literal null}.
|
||||
* @since 1.8
|
||||
*/
|
||||
public void onAfterLoad(AfterLoadEvent<E> event) {
|
||||
onAfterLoad(event.getDBObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures raw {@link com.mongodb.DBObject} and converted domain type after conversion.
|
||||
*
|
||||
* @param dbo can be {@literal null}.
|
||||
* @param source will never be {@literal null}.
|
||||
* @deprecated since 1.8. Please use {@link #onAfterConvert(AfterConvertEvent)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public void onAfterConvert(DBObject dbo, E source) {
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("onAfterConvert({}, {})", dbo, source);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures {@link AfterConvertEvent}.
|
||||
*
|
||||
* @param event will never be {@literal null}.
|
||||
* @since 1.8
|
||||
*/
|
||||
public void onAfterConvert(AfterConvertEvent<E> event) {
|
||||
onAfterConvert(event.getDBObject(), event.getSource());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures {@link com.mongodb.DBObject} after delete.
|
||||
*
|
||||
* @param dbo can be {@literal null}.
|
||||
* @deprecated since 1.8. Please use {@link #onAfterDelete(AfterDeleteEvent)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public void onAfterDelete(DBObject dbo) {
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("onAfterDelete({})", dbo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures {@link AfterDeleteEvent}.
|
||||
*
|
||||
* @param event will never be {@literal null}.
|
||||
* @since 1.8
|
||||
*/
|
||||
public void onAfterDelete(AfterDeleteEvent<E> event) {
|
||||
onAfterDelete(event.getDBObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Capture {@link com.mongodb.DBObject} before delete.
|
||||
*
|
||||
* @param dbo can be {@literal null}.
|
||||
* @deprecated since 1.8. Please use {@link #onBeforeDelete(BeforeDeleteEvent)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public void onBeforeDelete(DBObject dbo) {
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("onBeforeDelete({})", dbo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Capture {@link BeforeDeleteEvent}.
|
||||
*
|
||||
* @param event will never be {@literal null}.
|
||||
* @since 1.8
|
||||
*/
|
||||
public void onBeforeDelete(BeforeDeleteEvent<E> event) {
|
||||
onBeforeDelete(event.getDBObject());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011-2015 by the original author(s).
|
||||
* Copyright (c) 2011 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.
|
||||
@@ -13,42 +13,20 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.mongodb.core.mapping.event;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* {@link MongoMappingEvent} thrown after convert of a document.
|
||||
*
|
||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class AfterConvertEvent<E> extends MongoMappingEvent<E> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Creates new {@link AfterConvertEvent}.
|
||||
*
|
||||
* @param dbo can be {@literal null}.
|
||||
* @param source must not be {@literal null}.
|
||||
* @deprecated since 1.8. Please use {@link #AfterConvertEvent(DBObject, Object, String)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public AfterConvertEvent(DBObject dbo, E source) {
|
||||
this(dbo, source, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new {@link AfterConvertEvent}.
|
||||
*
|
||||
* @param dbo can be {@literal null}.
|
||||
* @param source must not be {@literal null}.
|
||||
* @param collectionName can be {@literal null}.
|
||||
* @since 1.8
|
||||
*/
|
||||
public AfterConvertEvent(DBObject dbo, E source, String collectionName) {
|
||||
super(source, dbo, collectionName);
|
||||
super(source, dbo);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2015 by the original author(s).
|
||||
* Copyright 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.
|
||||
@@ -22,7 +22,6 @@ import com.mongodb.DBObject;
|
||||
* will be the query document <em>after</am> it has been mapped onto the domain type handled.
|
||||
*
|
||||
* @author Martin Baumgartner
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class AfterDeleteEvent<T> extends AbstractDeleteEvent<T> {
|
||||
|
||||
@@ -33,22 +32,8 @@ public class AfterDeleteEvent<T> extends AbstractDeleteEvent<T> {
|
||||
*
|
||||
* @param dbo must not be {@literal null}.
|
||||
* @param type can be {@literal null}.
|
||||
* @deprecated since 1.8. Please use {@link #AfterDeleteEvent(DBObject, Class, String)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public AfterDeleteEvent(DBObject dbo, Class<T> type) {
|
||||
this(dbo, type, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link AfterDeleteEvent} for the given {@link DBObject}, type and collectionName.
|
||||
*
|
||||
* @param dbo must not be {@literal null}.
|
||||
* @param type can be {@literal null}.
|
||||
* @param collectionName can be {@literal null}.
|
||||
* @since 1.8
|
||||
*/
|
||||
public AfterDeleteEvent(DBObject dbo, Class<T> type, String collectionName) {
|
||||
super(dbo, type, collectionName);
|
||||
super(dbo, type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011-2015 by the original author(s).
|
||||
* Copyright (c) 2011 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.
|
||||
@@ -26,7 +26,6 @@ import com.mongodb.DBObject;
|
||||
* @author Oliver Gierke
|
||||
* @author Jon Brisbin
|
||||
* @author Christoph Leiter
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class AfterLoadEvent<T> extends MongoMappingEvent<DBObject> {
|
||||
|
||||
@@ -37,25 +36,11 @@ public class AfterLoadEvent<T> extends MongoMappingEvent<DBObject> {
|
||||
* Creates a new {@link AfterLoadEvent} for the given {@link DBObject} and type.
|
||||
*
|
||||
* @param dbo must not be {@literal null}.
|
||||
* @param type can be {@literal null}.
|
||||
* @deprecated since 1.8. Please use {@link #AfterLoadEvent(DBObject, Class, String)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public AfterLoadEvent(DBObject dbo, Class<T> type) {
|
||||
this(dbo, type, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link AfterLoadEvent} for the given {@link DBObject}, type and collectionName.
|
||||
*
|
||||
* @param dbo must not be {@literal null}.
|
||||
* @param type must not be {@literal null}.
|
||||
* @param collectionName can be {@literal null}.
|
||||
* @since 1.8
|
||||
*/
|
||||
public AfterLoadEvent(DBObject dbo, Class<T> type, String collectionName) {
|
||||
public AfterLoadEvent(DBObject dbo, Class<T> type) {
|
||||
|
||||
super(dbo, dbo, collectionName);
|
||||
super(dbo, dbo);
|
||||
|
||||
Assert.notNull(type, "Type must not be null!");
|
||||
this.type = type;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011-2015 by the original author(s).
|
||||
* Copyright (c) 2011 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.
|
||||
@@ -19,37 +19,14 @@ package org.springframework.data.mongodb.core.mapping.event;
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* {@link MongoMappingEvent} triggered after save of a document.
|
||||
*
|
||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class AfterSaveEvent<E> extends MongoMappingEvent<E> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Creates new {@link AfterSaveEvent}
|
||||
*
|
||||
* @param source must not be {@literal null}.
|
||||
* @param dbo can be {@literal null}.
|
||||
* @deprecated since 1.8. Please use {@link #AfterSaveEvent(Object, DBObject, String)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public AfterSaveEvent(E source, DBObject dbo) {
|
||||
super(source, dbo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new {@link AfterSaveEvent}.
|
||||
*
|
||||
* @param source must not be {@literal null}.
|
||||
* @param dbo can be {@literal null}.
|
||||
* @param collectionName can be {@literal null}.
|
||||
* @since 1.8
|
||||
*/
|
||||
public AfterSaveEvent(E source, DBObject dbo, String collectionName) {
|
||||
super(source, dbo, collectionName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2015 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,31 +20,12 @@ package org.springframework.data.mongodb.core.mapping.event;
|
||||
*
|
||||
* @author Jon Brisbin
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class BeforeConvertEvent<T> extends MongoMappingEvent<T> {
|
||||
|
||||
private static final long serialVersionUID = 252614269008845243L;
|
||||
|
||||
/**
|
||||
* Creates new {@link BeforeConvertEvent}.
|
||||
*
|
||||
* @param source must not be {@literal null}.
|
||||
* @deprecated since 1.8. Please use {@link #BeforeConvertEvent(Object, String)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public BeforeConvertEvent(T source) {
|
||||
this(source, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new {@link BeforeConvertEvent}.
|
||||
*
|
||||
* @param source must not be {@literal null}.
|
||||
* @param collectionName can be {@literal null}.
|
||||
* @since 1.8
|
||||
*/
|
||||
public BeforeConvertEvent(T source, String collectionName) {
|
||||
super(source, null, collectionName);
|
||||
super(source, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2015 by the original author(s).
|
||||
* Copyright 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.
|
||||
@@ -22,7 +22,6 @@ import com.mongodb.DBObject;
|
||||
* document <em>before</em> being mapped based on the domain class handled.
|
||||
*
|
||||
* @author Martin Baumgartner
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class BeforeDeleteEvent<T> extends AbstractDeleteEvent<T> {
|
||||
|
||||
@@ -33,22 +32,8 @@ public class BeforeDeleteEvent<T> extends AbstractDeleteEvent<T> {
|
||||
*
|
||||
* @param dbo must not be {@literal null}.
|
||||
* @param type can be {@literal null}.
|
||||
* @deprecated since 1.8. Please use {@link #BeforeDeleteEvent(DBObject, Class, String)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public BeforeDeleteEvent(DBObject dbo, Class<T> type) {
|
||||
this(dbo, type, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link BeforeDeleteEvent} for the given {@link DBObject}, type and collectionName.
|
||||
*
|
||||
* @param dbo must not be {@literal null}.
|
||||
* @param type can be {@literal null}.
|
||||
* @param collectionName can be {@literal null}.
|
||||
* @since 1.8
|
||||
*/
|
||||
public BeforeDeleteEvent(DBObject dbo, Class<T> type, String collectionName) {
|
||||
super(dbo, type, collectionName);
|
||||
super(dbo, type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011-2015 by the original author(s).
|
||||
* Copyright (c) 2011 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.
|
||||
@@ -19,37 +19,14 @@ package org.springframework.data.mongodb.core.mapping.event;
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* {@link MongoMappingEvent} triggered before save of a document.
|
||||
*
|
||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class BeforeSaveEvent<E> extends MongoMappingEvent<E> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Creates new {@link BeforeSaveEvent}.
|
||||
*
|
||||
* @param source must not be {@literal null}.
|
||||
* @param dbo can be {@literal null}.
|
||||
* @deprecated since 1.8. Please use {@link #BeforeSaveEvent(Object, DBObject, String)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public BeforeSaveEvent(E source, DBObject dbo) {
|
||||
super(source, dbo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new {@link BeforeSaveEvent}.
|
||||
*
|
||||
* @param source must not be {@literal null}.
|
||||
* @param dbo can be {@literal null}.
|
||||
* @param collectionName can be {@literal null}.
|
||||
* @since 1.8
|
||||
*/
|
||||
public BeforeSaveEvent(E source, DBObject dbo, String collectionName) {
|
||||
super(source, dbo, collectionName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011-2015 by the original author(s).
|
||||
* Copyright (c) 2011 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.
|
||||
@@ -16,69 +16,26 @@
|
||||
|
||||
package org.springframework.data.mongodb.core.mapping.event;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* Base {@link ApplicationEvent} triggered by Spring Data MongoDB.
|
||||
*
|
||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class MongoMappingEvent<T> extends ApplicationEvent {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final DBObject dbo;
|
||||
private final String collectionName;
|
||||
|
||||
/**
|
||||
* Creates new {@link MongoMappingEvent}.
|
||||
*
|
||||
* @param source must not be {@literal null}.
|
||||
* @param dbo can be {@literal null}.
|
||||
* @deprecated since 1.8. Please use {@link #MongoMappingEvent(Object, DBObject, String)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public MongoMappingEvent(T source, DBObject dbo) {
|
||||
this(source, dbo, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new {@link MongoMappingEvent}.
|
||||
*
|
||||
* @param source must not be {@literal null}.
|
||||
* @param dbo can be {@literal null}.
|
||||
* @param collectionName can be {@literal null}.
|
||||
*/
|
||||
public MongoMappingEvent(T source, DBObject dbo, String collectionName) {
|
||||
|
||||
super(source);
|
||||
this.dbo = dbo;
|
||||
this.collectionName = collectionName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@literal null} if not set.
|
||||
*/
|
||||
public DBObject getDBObject() {
|
||||
return dbo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the collection the event refers to.
|
||||
*
|
||||
* @return {@literal null} if not set.
|
||||
* @since 1.8
|
||||
*/
|
||||
public String getCollectionName() {
|
||||
return collectionName;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.EventObject#getSource()
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
@Override
|
||||
public T getSource() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 the original author or authors.
|
||||
* Copyright 2010-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -28,6 +28,7 @@ import com.mongodb.util.JSON;
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
* @author Thomas Darimont
|
||||
* @author John Willemin
|
||||
*/
|
||||
public class BasicQuery extends Query {
|
||||
|
||||
@@ -70,6 +71,19 @@ public class BasicQuery extends Query {
|
||||
|
||||
@Override
|
||||
public DBObject getFieldsObject() {
|
||||
|
||||
if (fieldsObject == null) {
|
||||
return super.getFieldsObject();
|
||||
}
|
||||
|
||||
if (super.getFieldsObject() != null) {
|
||||
|
||||
DBObject combinedFieldsObject = new BasicDBObject();
|
||||
combinedFieldsObject.putAll(fieldsObject);
|
||||
combinedFieldsObject.putAll(super.getFieldsObject());
|
||||
return combinedFieldsObject;
|
||||
}
|
||||
|
||||
return fieldsObject;
|
||||
}
|
||||
|
||||
|
||||
@@ -191,8 +191,8 @@ public class Criteria implements CriteriaDefinition {
|
||||
*/
|
||||
public Criteria in(Object... o) {
|
||||
if (o.length > 1 && o[1] instanceof Collection) {
|
||||
throw new InvalidMongoDbApiUsageException(
|
||||
"You can only pass in one argument of type " + o[1].getClass().getName());
|
||||
throw new InvalidMongoDbApiUsageException("You can only pass in one argument of type "
|
||||
+ o[1].getClass().getName());
|
||||
}
|
||||
criteria.put("$in", Arrays.asList(o));
|
||||
return this;
|
||||
@@ -434,23 +434,7 @@ public class Criteria implements CriteriaDefinition {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates criterion using {@code $geoIntersects} operator which matches intersections of the given {@code geoJson}
|
||||
* structure and the documents one. Requires MongoDB 2.4 or better.
|
||||
*
|
||||
* @param geoJson must not be {@literal null}.
|
||||
* @return
|
||||
* @since 1.8
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public Criteria intersects(GeoJson geoJson) {
|
||||
|
||||
Assert.notNull(geoJson, "GeoJson must not be null!");
|
||||
criteria.put("$geoIntersects", geoJson);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a geo-spatial criterion using a {@literal $maxDistance} operation, for use with $near
|
||||
* Creates a geospatical criterion using a {@literal $maxDistance} operation, for use with $near
|
||||
*
|
||||
* @see http://docs.mongodb.org/manual/reference/operator/query/maxDistance/
|
||||
* @param maxDistance
|
||||
@@ -543,8 +527,8 @@ public class Criteria implements CriteriaDefinition {
|
||||
private Criteria registerCriteriaChainElement(Criteria criteria) {
|
||||
|
||||
if (lastOperatorWasNot()) {
|
||||
throw new IllegalArgumentException(
|
||||
"operator $not is not allowed around criteria chain element: " + criteria.getCriteriaObject());
|
||||
throw new IllegalArgumentException("operator $not is not allowed around criteria chain element: "
|
||||
+ criteria.getCriteriaObject());
|
||||
} else {
|
||||
criteriaChain.add(criteria);
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ import org.springframework.context.annotation.ComponentScan.Filter;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.data.mongodb.repository.support.MongoRepositoryFactoryBean;
|
||||
import org.springframework.data.repository.config.DefaultRepositoryBaseClass;
|
||||
import org.springframework.data.repository.query.QueryLookupStrategy;
|
||||
import org.springframework.data.repository.query.QueryLookupStrategy.Key;
|
||||
|
||||
@@ -108,14 +107,6 @@ public @interface EnableMongoRepositories {
|
||||
*/
|
||||
Class<?> repositoryFactoryBeanClass() default MongoRepositoryFactoryBean.class;
|
||||
|
||||
/**
|
||||
* Configure the repository base class to be used to create repository proxies for this particular configuration.
|
||||
*
|
||||
* @return
|
||||
* @since 1.8
|
||||
*/
|
||||
Class<?> repositoryBaseClass() default DefaultRepositoryBaseClass.class;
|
||||
|
||||
/**
|
||||
* Configures the name of the {@link MongoTemplate} bean to be used with the repositories detected.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2016 the original author or authors.
|
||||
* Copyright 2010-2015 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,25 +15,31 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.repository.query;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.data.convert.EntityInstantiators;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Range;
|
||||
import org.springframework.data.domain.Slice;
|
||||
import org.springframework.data.domain.SliceImpl;
|
||||
import org.springframework.data.geo.Distance;
|
||||
import org.springframework.data.geo.GeoPage;
|
||||
import org.springframework.data.geo.GeoResult;
|
||||
import org.springframework.data.geo.GeoResults;
|
||||
import org.springframework.data.geo.Point;
|
||||
import org.springframework.data.mongodb.core.MongoOperations;
|
||||
import org.springframework.data.mongodb.core.query.NearQuery;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.data.mongodb.repository.query.MongoQueryExecution.CollectionExecution;
|
||||
import org.springframework.data.mongodb.repository.query.MongoQueryExecution.DeleteExecution;
|
||||
import org.springframework.data.mongodb.repository.query.MongoQueryExecution.GeoNearExecution;
|
||||
import org.springframework.data.mongodb.repository.query.MongoQueryExecution.PagedExecution;
|
||||
import org.springframework.data.mongodb.repository.query.MongoQueryExecution.PagingGeoNearExecution;
|
||||
import org.springframework.data.mongodb.repository.query.MongoQueryExecution.ResultProcessingConverter;
|
||||
import org.springframework.data.mongodb.repository.query.MongoQueryExecution.ResultProcessingExecution;
|
||||
import org.springframework.data.mongodb.repository.query.MongoQueryExecution.SingleEntityExecution;
|
||||
import org.springframework.data.mongodb.repository.query.MongoQueryExecution.SlicedExecution;
|
||||
import org.springframework.data.mongodb.repository.query.MongoQueryExecution.StreamExecution;
|
||||
import org.springframework.data.repository.query.ParameterAccessor;
|
||||
import org.springframework.data.repository.query.RepositoryQuery;
|
||||
import org.springframework.data.repository.query.ResultProcessor;
|
||||
import org.springframework.data.util.CloseableIterator;
|
||||
import org.springframework.data.util.StreamUtils;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.mongodb.WriteResult;
|
||||
|
||||
/**
|
||||
* Base class for {@link RepositoryQuery} implementations for Mongo.
|
||||
*
|
||||
@@ -45,7 +51,6 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
|
||||
|
||||
private final MongoQueryMethod method;
|
||||
private final MongoOperations operations;
|
||||
private final EntityInstantiators instantiators;
|
||||
|
||||
/**
|
||||
* Creates a new {@link AbstractMongoQuery} from the given {@link MongoQueryMethod} and {@link MongoOperations}.
|
||||
@@ -55,12 +60,11 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
|
||||
*/
|
||||
public AbstractMongoQuery(MongoQueryMethod method, MongoOperations operations) {
|
||||
|
||||
Assert.notNull(operations, "MongoOperations must not be null!");
|
||||
Assert.notNull(method, "MongoQueryMethod must not be null!");
|
||||
Assert.notNull(operations);
|
||||
Assert.notNull(method);
|
||||
|
||||
this.method = method;
|
||||
this.operations = operations;
|
||||
this.instantiators = new EntityInstantiators();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -82,53 +86,30 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
|
||||
|
||||
applyQueryMetaAttributesWhenPresent(query);
|
||||
|
||||
ResultProcessor processor = method.getResultProcessor().withDynamicProjection(accessor);
|
||||
String collection = method.getEntityInformation().getCollectionName();
|
||||
|
||||
MongoQueryExecution execution = getExecution(query, accessor,
|
||||
new ResultProcessingConverter(processor, operations, instantiators));
|
||||
|
||||
return execution.execute(query, processor.getReturnedType().getDomainType(), collection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the execution instance to use.
|
||||
*
|
||||
* @param query must not be {@literal null}.
|
||||
* @param parameters must not be {@literal null}.
|
||||
* @param accessor must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
private MongoQueryExecution getExecution(Query query, MongoParameterAccessor accessor,
|
||||
Converter<Object, Object> resultProcessing) {
|
||||
|
||||
if (method.isStreamQuery()) {
|
||||
return new StreamExecution(operations, resultProcessing);
|
||||
}
|
||||
|
||||
return new ResultProcessingExecution(getExecutionToWrap(query, accessor), resultProcessing);
|
||||
}
|
||||
|
||||
private MongoQueryExecution getExecutionToWrap(Query query, MongoParameterAccessor accessor) {
|
||||
|
||||
if (isDeleteQuery()) {
|
||||
return new DeleteExecution(operations, method);
|
||||
return new StreamExecution().execute(query);
|
||||
} else if (isDeleteQuery()) {
|
||||
return new DeleteExecution().execute(query);
|
||||
} else if (method.isGeoNearQuery() && method.isPageQuery()) {
|
||||
return new PagingGeoNearExecution(operations, accessor, method.getReturnType(), this);
|
||||
|
||||
MongoParameterAccessor countAccessor = new MongoParametersParameterAccessor(method, parameters);
|
||||
Query countQuery = createCountQuery(new ConvertingParameterAccessor(operations.getConverter(), countAccessor));
|
||||
|
||||
return new GeoNearExecution(accessor).execute(query, countQuery);
|
||||
} else if (method.isGeoNearQuery()) {
|
||||
return new GeoNearExecution(operations, accessor, method.getReturnType());
|
||||
return new GeoNearExecution(accessor).execute(query);
|
||||
} else if (method.isSliceQuery()) {
|
||||
return new SlicedExecution(operations, accessor.getPageable());
|
||||
return new SlicedExecution(accessor.getPageable()).execute(query);
|
||||
} else if (method.isCollectionQuery()) {
|
||||
return new CollectionExecution(operations, accessor.getPageable());
|
||||
return new CollectionExecution(accessor.getPageable()).execute(query);
|
||||
} else if (method.isPageQuery()) {
|
||||
return new PagedExecution(operations, accessor.getPageable());
|
||||
return new PagedExecution(accessor.getPageable()).execute(query);
|
||||
} else {
|
||||
return new SingleEntityExecution(operations, isCountQuery());
|
||||
return new SingleEntityExecution(isCountQuery()).execute(query);
|
||||
}
|
||||
}
|
||||
|
||||
Query applyQueryMetaAttributesWhenPresent(Query query) {
|
||||
private Query applyQueryMetaAttributesWhenPresent(Query query) {
|
||||
|
||||
if (method.hasQueryMetaAttributes()) {
|
||||
query.setMeta(method.getQueryMetaAttributes());
|
||||
@@ -146,7 +127,12 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
|
||||
* @return
|
||||
*/
|
||||
protected Query createCountQuery(ConvertingParameterAccessor accessor) {
|
||||
return applyQueryMetaAttributesWhenPresent(createQuery(accessor));
|
||||
|
||||
Query query = createQuery(accessor);
|
||||
|
||||
applyQueryMetaAttributesWhenPresent(query);
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -171,4 +157,292 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
|
||||
* @since 1.5
|
||||
*/
|
||||
protected abstract boolean isDeleteQuery();
|
||||
|
||||
private abstract class Execution {
|
||||
|
||||
abstract Object execute(Query query);
|
||||
|
||||
protected List<?> readCollection(Query query) {
|
||||
|
||||
MongoEntityMetadata<?> metadata = method.getEntityInformation();
|
||||
|
||||
String collectionName = metadata.getCollectionName();
|
||||
return operations.find(query, metadata.getJavaType(), collectionName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Execution} for collection returning queries.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
final class CollectionExecution extends Execution {
|
||||
|
||||
private final Pageable pageable;
|
||||
|
||||
CollectionExecution(Pageable pageable) {
|
||||
this.pageable = pageable;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.repository.query.AbstractMongoQuery.Execution#execute(org.springframework.data.mongodb.core.query.Query)
|
||||
*/
|
||||
@Override
|
||||
public Object execute(Query query) {
|
||||
return readCollection(query.with(pageable));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Execution} for {@link Slice} query methods.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
* @since 1.5
|
||||
*/
|
||||
|
||||
final class SlicedExecution extends Execution {
|
||||
|
||||
private final Pageable pageable;
|
||||
|
||||
SlicedExecution(Pageable pageable) {
|
||||
this.pageable = pageable;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.repository.query.AbstractMongoQuery.Execution#execute(org.springframework.data.mongodb.core.query.Query)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
Object execute(Query query) {
|
||||
|
||||
MongoEntityMetadata<?> metadata = method.getEntityInformation();
|
||||
int pageSize = pageable.getPageSize();
|
||||
|
||||
// Apply Pageable but tweak limit to peek into next page
|
||||
Query modifiedQuery = query.with(pageable).limit(pageSize + 1);
|
||||
|
||||
List result = operations.find(modifiedQuery, metadata.getJavaType(), metadata.getCollectionName());
|
||||
|
||||
boolean hasNext = result.size() > pageSize;
|
||||
|
||||
return new SliceImpl<Object>(hasNext ? result.subList(0, pageSize) : result, pageable, hasNext);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Execution} for pagination queries.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
final class PagedExecution extends Execution {
|
||||
|
||||
private final Pageable pageable;
|
||||
|
||||
/**
|
||||
* Creates a new {@link PagedExecution}.
|
||||
*
|
||||
* @param pageable
|
||||
*/
|
||||
public PagedExecution(Pageable pageable) {
|
||||
|
||||
Assert.notNull(pageable);
|
||||
this.pageable = pageable;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.repository.AbstractMongoQuery.Execution#execute(org.springframework.data.mongodb.core.query.Query)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
Object execute(Query query) {
|
||||
|
||||
MongoEntityMetadata<?> metadata = method.getEntityInformation();
|
||||
String collectionName = metadata.getCollectionName();
|
||||
Class<?> type = metadata.getJavaType();
|
||||
|
||||
int overallLimit = query.getLimit();
|
||||
long count = operations.count(query, type, collectionName);
|
||||
count = overallLimit != 0 ? Math.min(count, query.getLimit()) : count;
|
||||
|
||||
boolean pageableOutOfScope = pageable.getOffset() > count;
|
||||
|
||||
if (pageableOutOfScope) {
|
||||
return new PageImpl<Object>(Collections.emptyList(), pageable, count);
|
||||
}
|
||||
|
||||
// Apply raw pagination
|
||||
query = query.with(pageable);
|
||||
|
||||
// Adjust limit if page would exceed the overall limit
|
||||
if (overallLimit != 0 && pageable.getOffset() + pageable.getPageSize() > overallLimit) {
|
||||
query.limit(overallLimit - pageable.getOffset());
|
||||
}
|
||||
|
||||
List<?> result = operations.find(query, type, collectionName);
|
||||
return new PageImpl(result, pageable, count);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Execution} to return a single entity.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
final class SingleEntityExecution extends Execution {
|
||||
|
||||
private final boolean countProjection;
|
||||
|
||||
private SingleEntityExecution(boolean countProjection) {
|
||||
this.countProjection = countProjection;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.repository.AbstractMongoQuery.Execution#execute(org.springframework.data.mongodb.core.core.query.Query)
|
||||
*/
|
||||
@Override
|
||||
Object execute(Query query) {
|
||||
|
||||
MongoEntityMetadata<?> metadata = method.getEntityInformation();
|
||||
return countProjection ? operations.count(query, metadata.getJavaType()) : operations.findOne(query,
|
||||
metadata.getJavaType(), metadata.getCollectionName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Execution} to execute geo-near queries.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
final class GeoNearExecution extends Execution {
|
||||
|
||||
private final MongoParameterAccessor accessor;
|
||||
|
||||
public GeoNearExecution(MongoParameterAccessor accessor) {
|
||||
this.accessor = accessor;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.repository.AbstractMongoQuery.Execution#execute(org.springframework.data.mongodb.core.query.Query)
|
||||
*/
|
||||
@Override
|
||||
Object execute(Query query) {
|
||||
|
||||
GeoResults<?> results = doExecuteQuery(query);
|
||||
return isListOfGeoResult() ? results.getContent() : results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the given {@link Query} to return a page.
|
||||
*
|
||||
* @param query must not be {@literal null}.
|
||||
* @param countQuery must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
Object execute(Query query, Query countQuery) {
|
||||
|
||||
MongoEntityMetadata<?> metadata = method.getEntityInformation();
|
||||
long count = operations.count(countQuery, metadata.getCollectionName());
|
||||
|
||||
return new GeoPage<Object>(doExecuteQuery(query), accessor.getPageable(), count);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private GeoResults<Object> doExecuteQuery(Query query) {
|
||||
|
||||
Point nearLocation = accessor.getGeoNearLocation();
|
||||
NearQuery nearQuery = NearQuery.near(nearLocation);
|
||||
|
||||
if (query != null) {
|
||||
nearQuery.query(query);
|
||||
}
|
||||
|
||||
Range<Distance> distances = accessor.getDistanceRange();
|
||||
Distance maxDistance = distances.getUpperBound();
|
||||
|
||||
if (maxDistance != null) {
|
||||
nearQuery.maxDistance(maxDistance).in(maxDistance.getMetric());
|
||||
}
|
||||
|
||||
Distance minDistance = distances.getLowerBound();
|
||||
|
||||
if (minDistance != null) {
|
||||
nearQuery.minDistance(minDistance).in(minDistance.getMetric());
|
||||
}
|
||||
|
||||
Pageable pageable = accessor.getPageable();
|
||||
if (pageable != null) {
|
||||
nearQuery.with(pageable);
|
||||
}
|
||||
|
||||
MongoEntityMetadata<?> metadata = method.getEntityInformation();
|
||||
return (GeoResults<Object>) operations.geoNear(nearQuery, metadata.getJavaType(), metadata.getCollectionName());
|
||||
}
|
||||
|
||||
private boolean isListOfGeoResult() {
|
||||
|
||||
TypeInformation<?> returnType = method.getReturnType();
|
||||
|
||||
if (!returnType.getType().equals(List.class)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
TypeInformation<?> componentType = returnType.getComponentType();
|
||||
return componentType == null ? false : GeoResult.class.equals(componentType.getType());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Execution} removing documents matching the query.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
final class DeleteExecution extends Execution {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.repository.query.AbstractMongoQuery.Execution#execute(org.springframework.data.mongodb.core.query.Query)
|
||||
*/
|
||||
@Override
|
||||
Object execute(Query query) {
|
||||
|
||||
MongoEntityMetadata<?> metadata = method.getEntityInformation();
|
||||
return deleteAndConvertResult(query, metadata);
|
||||
}
|
||||
|
||||
private Object deleteAndConvertResult(Query query, MongoEntityMetadata<?> metadata) {
|
||||
|
||||
if (method.isCollectionQuery()) {
|
||||
return operations.findAllAndRemove(query, metadata.getJavaType(), metadata.getCollectionName());
|
||||
}
|
||||
|
||||
WriteResult writeResult = operations.remove(query, metadata.getJavaType(), metadata.getCollectionName());
|
||||
return writeResult != null ? writeResult.getN() : 0L;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @author Thomas Darimont
|
||||
* @since 1.7
|
||||
*/
|
||||
final class StreamExecution extends Execution {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.repository.query.AbstractMongoQuery.Execution#execute(org.springframework.data.mongodb.core.query.Query)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
Object execute(Query query) {
|
||||
|
||||
Class<?> entityType = getQueryMethod().getEntityInformation().getJavaType();
|
||||
|
||||
return StreamUtils.createStreamFromIterator((CloseableIterator<Object>) operations.stream(query, entityType));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,6 @@ import com.mongodb.DBRef;
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
* @author Thomas Darimont
|
||||
*/
|
||||
public class ConvertingParameterAccessor implements MongoParameterAccessor {
|
||||
|
||||
@@ -90,15 +89,6 @@ public class ConvertingParameterAccessor implements MongoParameterAccessor {
|
||||
return delegate.getSort();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.query.ParameterAccessor#getDynamicProjection()
|
||||
*/
|
||||
@Override
|
||||
public Class<?> getDynamicProjection() {
|
||||
return delegate.getDynamicProjection();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.query.ParameterAccessor#getBindableValue(int)
|
||||
@@ -226,7 +216,7 @@ 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 collection.
|
||||
* single-element collction
|
||||
*
|
||||
* @param source
|
||||
* @return
|
||||
@@ -250,15 +240,6 @@ public class ConvertingParameterAccessor implements MongoParameterAccessor {
|
||||
return source.getClass().isArray() ? CollectionUtils.arrayToList(source) : Collections.singleton(source);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.repository.query.MongoParameterAccessor#getValues()
|
||||
*/
|
||||
@Override
|
||||
public Object[] getValues() {
|
||||
return delegate.getValues();
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom {@link Iterator} that adds a method to access elements in a converted manner.
|
||||
*
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015-2016 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.core.convert.converter.Converter;
|
||||
import org.springframework.data.convert.EntityInstantiator;
|
||||
import org.springframework.data.convert.EntityInstantiators;
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
import org.springframework.data.mapping.PersistentProperty;
|
||||
import org.springframework.data.mapping.PersistentPropertyAccessor;
|
||||
import org.springframework.data.mapping.PreferredConstructor;
|
||||
import org.springframework.data.mapping.PreferredConstructor.Parameter;
|
||||
import org.springframework.data.mapping.SimplePropertyHandler;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mapping.model.ParameterValueProvider;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link Converter} to instantiate DTOs from fully equipped domain objects.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
class DtoInstantiatingConverter implements Converter<Object, Object> {
|
||||
|
||||
private final Class<?> targetType;
|
||||
private final MappingContext<? extends PersistentEntity<?, ?>, ? extends PersistentProperty<?>> context;
|
||||
private final EntityInstantiator instantiator;
|
||||
|
||||
/**
|
||||
* Creates a new {@link Converter} to instantiate DTOs.
|
||||
*
|
||||
* @param dtoType must not be {@literal null}.
|
||||
* @param context must not be {@literal null}.
|
||||
* @param instantiators must not be {@literal null}.
|
||||
*/
|
||||
public DtoInstantiatingConverter(Class<?> dtoType,
|
||||
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> context,
|
||||
EntityInstantiators instantiator) {
|
||||
|
||||
Assert.notNull(dtoType, "DTO type must not be null!");
|
||||
Assert.notNull(context, "MappingContext must not be null!");
|
||||
Assert.notNull(instantiator, "EntityInstantiators must not be null!");
|
||||
|
||||
this.targetType = dtoType;
|
||||
this.context = context;
|
||||
this.instantiator = instantiator.getInstantiatorFor(context.getPersistentEntity(dtoType));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public Object convert(Object source) {
|
||||
|
||||
if (targetType.isInterface()) {
|
||||
return source;
|
||||
}
|
||||
|
||||
final PersistentEntity<?, ?> sourceEntity = context.getPersistentEntity(source.getClass());
|
||||
final PersistentPropertyAccessor sourceAccessor = sourceEntity.getPropertyAccessor(source);
|
||||
final PersistentEntity<?, ?> targetEntity = context.getPersistentEntity(targetType);
|
||||
final PreferredConstructor<?, ? extends PersistentProperty<?>> constructor = targetEntity
|
||||
.getPersistenceConstructor();
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
Object dto = instantiator.createInstance(targetEntity, new ParameterValueProvider() {
|
||||
|
||||
@Override
|
||||
public Object getParameterValue(Parameter parameter) {
|
||||
return sourceAccessor.getProperty(sourceEntity.getPersistentProperty(parameter.getName()));
|
||||
}
|
||||
});
|
||||
|
||||
final PersistentPropertyAccessor dtoAccessor = targetEntity.getPropertyAccessor(dto);
|
||||
|
||||
targetEntity.doWithProperties(new SimplePropertyHandler() {
|
||||
|
||||
@Override
|
||||
public void doWithPersistentProperty(PersistentProperty<?> property) {
|
||||
|
||||
if (constructor.isConstructorParameter(property)) {
|
||||
return;
|
||||
}
|
||||
|
||||
dtoAccessor.setProperty(property,
|
||||
sourceAccessor.getProperty(sourceEntity.getPersistentProperty(property.getName())));
|
||||
}
|
||||
});
|
||||
|
||||
return dto;
|
||||
}
|
||||
}
|
||||
@@ -1,231 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 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.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.bind.DatatypeConverter;
|
||||
|
||||
import org.bson.BSON;
|
||||
import org.springframework.data.mongodb.repository.query.StringBasedMongoQuery.ParameterBinding;
|
||||
import org.springframework.data.repository.query.EvaluationContextProvider;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.mongodb.util.JSON;
|
||||
|
||||
/**
|
||||
* {@link ExpressionEvaluatingParameterBinder} allows to evaluate, convert and bind parameters to placholders within a
|
||||
* {@link String}.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Thomas Darimont
|
||||
* @author Oliver Gierke
|
||||
* @since 1.9
|
||||
*/
|
||||
class ExpressionEvaluatingParameterBinder {
|
||||
|
||||
private final SpelExpressionParser expressionParser;
|
||||
private final EvaluationContextProvider evaluationContextProvider;
|
||||
|
||||
/**
|
||||
* Creates new {@link ExpressionEvaluatingParameterBinder}
|
||||
*
|
||||
* @param expressionParser must not be {@literal null}.
|
||||
* @param evaluationContextProvider must not be {@literal null}.
|
||||
*/
|
||||
public ExpressionEvaluatingParameterBinder(SpelExpressionParser expressionParser,
|
||||
EvaluationContextProvider evaluationContextProvider) {
|
||||
|
||||
Assert.notNull(expressionParser, "ExpressionParser must not be null!");
|
||||
Assert.notNull(evaluationContextProvider, "EvaluationContextProvider must not be null!");
|
||||
|
||||
this.expressionParser = expressionParser;
|
||||
this.evaluationContextProvider = evaluationContextProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind values provided by {@link MongoParameterAccessor} to placeholders in {@literal raw} while considering
|
||||
* potential conversions and parameter types.
|
||||
*
|
||||
* @param raw can be {@literal null} or empty.
|
||||
* @param accessor must not be {@literal null}.
|
||||
* @param bindingContext must not be {@literal null}.
|
||||
* @return {@literal null} if given {@code raw} value is empty.
|
||||
*/
|
||||
public String bind(String raw, MongoParameterAccessor accessor, BindingContext bindingContext) {
|
||||
|
||||
if (!StringUtils.hasText(raw)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return replacePlaceholders(raw, accessor, bindingContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaced the parameter placeholders with the actual parameter values from the given {@link ParameterBinding}s.
|
||||
*
|
||||
* @param input must not be {@literal null} or empty.
|
||||
* @param accessor must not be {@literal null}.
|
||||
* @param bindings must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
private String replacePlaceholders(String input, MongoParameterAccessor accessor, BindingContext bindingContext) {
|
||||
|
||||
if (!bindingContext.hasBindings()) {
|
||||
return input;
|
||||
}
|
||||
|
||||
boolean isCompletlyParameterizedQuery = input.matches("^\\?\\d+$");
|
||||
StringBuilder result = new StringBuilder(input);
|
||||
|
||||
for (ParameterBinding binding : bindingContext.getBindings()) {
|
||||
|
||||
String parameter = binding.getParameter();
|
||||
int idx = result.indexOf(parameter);
|
||||
|
||||
if (idx == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String valueForBinding = getParameterValueForBinding(accessor, bindingContext.getParameters(), binding);
|
||||
|
||||
int start = idx;
|
||||
int end = idx + parameter.length();
|
||||
|
||||
// If the value to bind is an object literal we need to remove the quoting around the expression insertion point.
|
||||
if (valueForBinding.startsWith("{") && !isCompletlyParameterizedQuery) {
|
||||
|
||||
// Is the insertion point actually surrounded by quotes?
|
||||
char beforeStart = result.charAt(start - 1);
|
||||
char afterEnd = result.charAt(end);
|
||||
|
||||
if ((beforeStart == '\'' || beforeStart == '"') && (afterEnd == '\'' || afterEnd == '"')) {
|
||||
|
||||
// Skip preceding and following quote
|
||||
start -= 1;
|
||||
end += 1;
|
||||
}
|
||||
}
|
||||
|
||||
result.replace(start, end, valueForBinding);
|
||||
}
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the serialized value to be used for the given {@link ParameterBinding}.
|
||||
*
|
||||
* @param accessor must not be {@literal null}.
|
||||
* @param parameters
|
||||
* @param binding must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
private String getParameterValueForBinding(MongoParameterAccessor accessor, MongoParameters parameters,
|
||||
ParameterBinding binding) {
|
||||
|
||||
Object value = binding.isExpression()
|
||||
? evaluateExpression(binding.getExpression(), parameters, accessor.getValues())
|
||||
: accessor.getBindableValue(binding.getParameterIndex());
|
||||
|
||||
if (value instanceof String && binding.isQuoted()) {
|
||||
return (String) value;
|
||||
}
|
||||
|
||||
if (value instanceof byte[]) {
|
||||
|
||||
String base64representation = DatatypeConverter.printBase64Binary((byte[]) value);
|
||||
|
||||
if (!binding.isQuoted()) {
|
||||
return "{ '$binary' : '" + base64representation + "', '$type' : " + BSON.B_GENERAL + "}";
|
||||
}
|
||||
|
||||
return base64representation;
|
||||
}
|
||||
|
||||
return JSON.serialize(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates the given {@code expressionString}.
|
||||
*
|
||||
* @param expressionString must not be {@literal null} or empty.
|
||||
* @param parameters must not be {@literal null}.
|
||||
* @param parameterValues must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
private Object evaluateExpression(String expressionString, MongoParameters parameters, Object[] parameterValues) {
|
||||
|
||||
EvaluationContext evaluationContext = evaluationContextProvider.getEvaluationContext(parameters, parameterValues);
|
||||
Expression expression = expressionParser.parseExpression(expressionString);
|
||||
|
||||
return expression.getValue(evaluationContext, Object.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 1.9
|
||||
*/
|
||||
static class BindingContext {
|
||||
|
||||
final MongoParameters parameters;
|
||||
final List<ParameterBinding> bindings;
|
||||
|
||||
/**
|
||||
* Creates new {@link BindingContext}.
|
||||
*
|
||||
* @param parameters
|
||||
* @param bindings
|
||||
*/
|
||||
public BindingContext(MongoParameters parameters, List<ParameterBinding> bindings) {
|
||||
|
||||
this.parameters = parameters;
|
||||
this.bindings = bindings;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@literal true} when list of bindings is not empty.
|
||||
*/
|
||||
boolean hasBindings() {
|
||||
return !CollectionUtils.isEmpty(bindings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get unmodifiable list of {@link ParameterBinding}s.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
*/
|
||||
public List<ParameterBinding> getBindings() {
|
||||
return Collections.unmodifiableList(bindings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the associated {@link MongoParameters}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public MongoParameters getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,6 @@ import org.springframework.data.repository.query.ParameterAccessor;
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
* @author Thomas Darimont
|
||||
*/
|
||||
public interface MongoParameterAccessor extends ParameterAccessor {
|
||||
|
||||
@@ -52,12 +51,4 @@ public interface MongoParameterAccessor extends ParameterAccessor {
|
||||
* @since 1.6
|
||||
*/
|
||||
TextCriteria getFullText();
|
||||
|
||||
/**
|
||||
* Returns the raw parameter values of the underlying query method.
|
||||
*
|
||||
* @return
|
||||
* @since 1.8
|
||||
*/
|
||||
Object[] getValues();
|
||||
}
|
||||
|
||||
@@ -32,25 +32,22 @@ import org.springframework.util.ClassUtils;
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
* @author Thomas Darimont
|
||||
*/
|
||||
public class MongoParametersParameterAccessor extends ParametersParameterAccessor implements MongoParameterAccessor {
|
||||
|
||||
private final MongoQueryMethod method;
|
||||
private final List<Object> values;
|
||||
|
||||
/**
|
||||
* Creates a new {@link MongoParametersParameterAccessor}.
|
||||
*
|
||||
* @param method must not be {@literal null}.
|
||||
* @param values must not be {@literal null}.
|
||||
* @param values must not be {@@iteral null}.
|
||||
*/
|
||||
public MongoParametersParameterAccessor(MongoQueryMethod method, Object[] values) {
|
||||
|
||||
super(method.getParameters(), values);
|
||||
|
||||
this.method = method;
|
||||
this.values = Arrays.asList(values);
|
||||
}
|
||||
|
||||
public Range<Distance> getDistanceRange() {
|
||||
@@ -125,17 +122,8 @@ public class MongoParametersParameterAccessor extends ParametersParameterAccesso
|
||||
return ((TextCriteria) fullText);
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Expected full text parameter to be one of String, Term or TextCriteria but found %s.",
|
||||
ClassUtils.getShortName(fullText.getClass())));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.repository.query.MongoParameterAccessor#getValues()
|
||||
*/
|
||||
@Override
|
||||
public Object[] getValues() {
|
||||
return values.toArray();
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"Expected full text parameter to be one of String, Term or TextCriteria but found %s.",
|
||||
ClassUtils.getShortName(fullText.getClass())));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,31 +169,32 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
|
||||
* @param parameters
|
||||
* @return
|
||||
*/
|
||||
private Criteria from(Part part, MongoPersistentProperty property, Criteria criteria, Iterator<Object> parameters) {
|
||||
private Criteria from(Part part, MongoPersistentProperty property, Criteria criteria,
|
||||
PotentiallyConvertingIterator parameters) {
|
||||
|
||||
Type type = part.getType();
|
||||
|
||||
switch (type) {
|
||||
case AFTER:
|
||||
case GREATER_THAN:
|
||||
return criteria.gt(parameters.next());
|
||||
return criteria.gt(parameters.nextConverted(property));
|
||||
case GREATER_THAN_EQUAL:
|
||||
return criteria.gte(parameters.next());
|
||||
return criteria.gte(parameters.nextConverted(property));
|
||||
case BEFORE:
|
||||
case LESS_THAN:
|
||||
return criteria.lt(parameters.next());
|
||||
return criteria.lt(parameters.nextConverted(property));
|
||||
case LESS_THAN_EQUAL:
|
||||
return criteria.lte(parameters.next());
|
||||
return criteria.lte(parameters.nextConverted(property));
|
||||
case BETWEEN:
|
||||
return criteria.gt(parameters.next()).lt(parameters.next());
|
||||
return criteria.gt(parameters.nextConverted(property)).lt(parameters.nextConverted(property));
|
||||
case IS_NOT_NULL:
|
||||
return criteria.ne(null);
|
||||
case IS_NULL:
|
||||
return criteria.is(null);
|
||||
case NOT_IN:
|
||||
return criteria.nin(nextAsArray(parameters));
|
||||
return criteria.nin(nextAsArray(parameters, property));
|
||||
case IN:
|
||||
return criteria.in(nextAsArray(parameters));
|
||||
return criteria.in(nextAsArray(parameters, property));
|
||||
case LIKE:
|
||||
case STARTING_WITH:
|
||||
case ENDING_WITH:
|
||||
@@ -240,12 +241,12 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
|
||||
return criteria.within((Shape) parameter);
|
||||
case SIMPLE_PROPERTY:
|
||||
|
||||
return isSimpleComparisionPossible(part) ? criteria.is(parameters.next())
|
||||
return isSimpleComparisionPossible(part) ? criteria.is(parameters.nextConverted(property))
|
||||
: createLikeRegexCriteriaOrThrow(part, property, criteria, parameters, false);
|
||||
|
||||
case NEGATING_SIMPLE_PROPERTY:
|
||||
|
||||
return isSimpleComparisionPossible(part) ? criteria.ne(parameters.next())
|
||||
return isSimpleComparisionPossible(part) ? criteria.ne(parameters.nextConverted(property))
|
||||
: createLikeRegexCriteriaOrThrow(part, property, criteria, parameters, true);
|
||||
default:
|
||||
throw new IllegalArgumentException("Unsupported keyword!");
|
||||
@@ -277,7 +278,7 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
|
||||
* @return the criteria extended with the like-regex.
|
||||
*/
|
||||
private Criteria createLikeRegexCriteriaOrThrow(Part part, MongoPersistentProperty property, Criteria criteria,
|
||||
Iterator<Object> parameters, boolean shouldNegateExpression) {
|
||||
PotentiallyConvertingIterator parameters, boolean shouldNegateExpression) {
|
||||
|
||||
PropertyPath path = part.getProperty().getLeafProperty();
|
||||
|
||||
@@ -296,7 +297,7 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
|
||||
criteria = criteria.not();
|
||||
}
|
||||
|
||||
return addAppropriateLikeRegexTo(criteria, part, parameters.next().toString());
|
||||
return addAppropriateLikeRegexTo(criteria, part, parameters.nextConverted(property).toString());
|
||||
|
||||
case NEVER:
|
||||
// intentional no-op
|
||||
@@ -318,10 +319,10 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
|
||||
* @return
|
||||
*/
|
||||
private Criteria createContainingCriteria(Part part, MongoPersistentProperty property, Criteria criteria,
|
||||
Iterator<Object> parameters) {
|
||||
PotentiallyConvertingIterator parameters) {
|
||||
|
||||
if (property.isCollectionLike()) {
|
||||
return criteria.in(nextAsArray(parameters));
|
||||
return criteria.in(nextAsArray(parameters, property));
|
||||
}
|
||||
|
||||
return addAppropriateLikeRegexTo(criteria, part, parameters.next().toString());
|
||||
@@ -376,9 +377,8 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
|
||||
String.format("Expected parameter type of %s but got %s!", type, parameter.getClass()));
|
||||
}
|
||||
|
||||
private Object[] nextAsArray(Iterator<Object> iterator) {
|
||||
|
||||
Object next = iterator.next();
|
||||
private Object[] nextAsArray(PotentiallyConvertingIterator iterator, MongoPersistentProperty property) {
|
||||
Object next = iterator.nextConverted(property);
|
||||
|
||||
if (next instanceof Collection) {
|
||||
return ((Collection<?>) next).toArray();
|
||||
|
||||
@@ -1,381 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 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 lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.data.convert.EntityInstantiators;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Range;
|
||||
import org.springframework.data.domain.Slice;
|
||||
import org.springframework.data.domain.SliceImpl;
|
||||
import org.springframework.data.geo.Distance;
|
||||
import org.springframework.data.geo.GeoPage;
|
||||
import org.springframework.data.geo.GeoResult;
|
||||
import org.springframework.data.geo.GeoResults;
|
||||
import org.springframework.data.geo.Point;
|
||||
import org.springframework.data.mongodb.core.MongoOperations;
|
||||
import org.springframework.data.mongodb.core.query.NearQuery;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.data.repository.query.ResultProcessor;
|
||||
import org.springframework.data.repository.query.ReturnedType;
|
||||
import org.springframework.data.util.CloseableIterator;
|
||||
import org.springframework.data.util.StreamUtils;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import com.mongodb.WriteResult;
|
||||
|
||||
interface MongoQueryExecution {
|
||||
|
||||
Object execute(Query query, Class<?> type, String collection);
|
||||
|
||||
/**
|
||||
* {@link MongoQueryExecution} for collection returning queries.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
static final class CollectionExecution implements MongoQueryExecution {
|
||||
|
||||
private final @NonNull MongoOperations operations;
|
||||
private final Pageable pageable;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.repository.query.AbstractMongoQuery.Execution#execute(org.springframework.data.mongodb.core.query.Query, java.lang.Class, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public Object execute(Query query, Class<?> type, String collection) {
|
||||
return operations.find(query.with(pageable), type, collection);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link MongoQueryExecution} for {@link Slice} query methods.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
* @since 1.5
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
static final class SlicedExecution implements MongoQueryExecution {
|
||||
|
||||
private final @NonNull MongoOperations operations;
|
||||
private final @NonNull Pageable pageable;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.repository.query.AbstractMongoQuery.Execution#execute(org.springframework.data.mongodb.core.query.Query, java.lang.Class, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public Object execute(Query query, Class<?> type, String collection) {
|
||||
|
||||
int pageSize = pageable.getPageSize();
|
||||
|
||||
// Apply Pageable but tweak limit to peek into next page
|
||||
Query modifiedQuery = query.with(pageable).limit(pageSize + 1);
|
||||
List result = operations.find(modifiedQuery, type, collection);
|
||||
|
||||
boolean hasNext = result.size() > pageSize;
|
||||
|
||||
return new SliceImpl<Object>(hasNext ? result.subList(0, pageSize) : result, pageable, hasNext);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link MongoQueryExecution} for pagination queries.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
static final class PagedExecution implements MongoQueryExecution {
|
||||
|
||||
private final @NonNull MongoOperations operations;
|
||||
private final @NonNull Pageable pageable;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.repository.query.AbstractMongoQuery.Execution#execute(org.springframework.data.mongodb.core.query.Query, java.lang.Class, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public Object execute(Query query, Class<?> type, String collection) {
|
||||
|
||||
int overallLimit = query.getLimit();
|
||||
long count = operations.count(query, type, collection);
|
||||
count = overallLimit != 0 ? Math.min(count, query.getLimit()) : count;
|
||||
|
||||
boolean pageableOutOfScope = pageable.getOffset() > count;
|
||||
|
||||
if (pageableOutOfScope) {
|
||||
return new PageImpl<Object>(Collections.emptyList(), pageable, count);
|
||||
}
|
||||
|
||||
// Apply raw pagination
|
||||
query = query.with(pageable);
|
||||
|
||||
// Adjust limit if page would exceed the overall limit
|
||||
if (overallLimit != 0 && pageable.getOffset() + pageable.getPageSize() > overallLimit) {
|
||||
query.limit(overallLimit - pageable.getOffset());
|
||||
}
|
||||
|
||||
List<?> result = operations.find(query, type, collection);
|
||||
return new PageImpl(result, pageable, count);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link MongoQueryExecution} to return a single entity.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
static final class SingleEntityExecution implements MongoQueryExecution {
|
||||
|
||||
private final MongoOperations operations;
|
||||
private final boolean countProjection;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.repository.query.AbstractMongoQuery.Execution#execute(org.springframework.data.mongodb.core.query.Query, java.lang.Class, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public Object execute(Query query, Class<?> type, String collection) {
|
||||
return countProjection ? operations.count(query, type, collection) : operations.findOne(query, type, collection);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link MongoQueryExecution} to execute geo-near queries.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
static class GeoNearExecution implements MongoQueryExecution {
|
||||
|
||||
private final MongoOperations operations;
|
||||
private final MongoParameterAccessor accessor;
|
||||
private final TypeInformation<?> returnType;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.repository.query.AbstractMongoQuery.Execution#execute(org.springframework.data.mongodb.core.query.Query, java.lang.Class, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public Object execute(Query query, Class<?> type, String collection) {
|
||||
|
||||
GeoResults<?> results = doExecuteQuery(query, type, collection);
|
||||
return isListOfGeoResult() ? results.getContent() : results;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected GeoResults<Object> doExecuteQuery(Query query, Class<?> type, String collection) {
|
||||
|
||||
Point nearLocation = accessor.getGeoNearLocation();
|
||||
NearQuery nearQuery = NearQuery.near(nearLocation);
|
||||
|
||||
if (query != null) {
|
||||
nearQuery.query(query);
|
||||
}
|
||||
|
||||
Range<Distance> distances = accessor.getDistanceRange();
|
||||
Distance maxDistance = distances.getUpperBound();
|
||||
|
||||
if (maxDistance != null) {
|
||||
nearQuery.maxDistance(maxDistance).in(maxDistance.getMetric());
|
||||
}
|
||||
|
||||
Distance minDistance = distances.getLowerBound();
|
||||
|
||||
if (minDistance != null) {
|
||||
nearQuery.minDistance(minDistance).in(minDistance.getMetric());
|
||||
}
|
||||
|
||||
Pageable pageable = accessor.getPageable();
|
||||
|
||||
if (pageable != null) {
|
||||
nearQuery.with(pageable);
|
||||
}
|
||||
|
||||
return (GeoResults<Object>) operations.geoNear(nearQuery, type, collection);
|
||||
}
|
||||
|
||||
private boolean isListOfGeoResult() {
|
||||
|
||||
if (!returnType.getType().equals(List.class)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
TypeInformation<?> componentType = returnType.getComponentType();
|
||||
return componentType == null ? false : GeoResult.class.equals(componentType.getType());
|
||||
}
|
||||
}
|
||||
|
||||
static final class PagingGeoNearExecution extends GeoNearExecution {
|
||||
|
||||
private final MongoOperations operations;
|
||||
private final MongoParameterAccessor accessor;
|
||||
private final AbstractMongoQuery mongoQuery;
|
||||
|
||||
public PagingGeoNearExecution(MongoOperations operations, MongoParameterAccessor accessor,
|
||||
TypeInformation<?> returnType, AbstractMongoQuery query) {
|
||||
|
||||
super(operations, accessor, returnType);
|
||||
|
||||
this.accessor = accessor;
|
||||
this.operations = operations;
|
||||
this.mongoQuery = query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the given {@link Query} to return a page.
|
||||
*
|
||||
* @param query must not be {@literal null}.
|
||||
* @param countQuery must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Object execute(Query query, Class<?> type, String collection) {
|
||||
|
||||
ConvertingParameterAccessor parameterAccessor = new ConvertingParameterAccessor(operations.getConverter(),
|
||||
accessor);
|
||||
Query countQuery = mongoQuery.applyQueryMetaAttributesWhenPresent(mongoQuery.createCountQuery(parameterAccessor));
|
||||
long count = operations.count(countQuery, collection);
|
||||
|
||||
return new GeoPage<Object>(doExecuteQuery(query, type, collection), accessor.getPageable(), count);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link MongoQueryExecution} removing documents matching the query.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
static final class DeleteExecution implements MongoQueryExecution {
|
||||
|
||||
private final MongoOperations operations;
|
||||
private final MongoQueryMethod method;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.repository.query.AbstractMongoQuery.Execution#execute(org.springframework.data.mongodb.core.query.Query, java.lang.Class, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public Object execute(Query query, Class<?> type, String collection) {
|
||||
|
||||
if (method.isCollectionQuery()) {
|
||||
return operations.findAllAndRemove(query, type, collection);
|
||||
}
|
||||
|
||||
WriteResult writeResult = operations.remove(query, type, collection);
|
||||
return writeResult != null ? writeResult.getN() : 0L;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @author Thomas Darimont
|
||||
* @since 1.7
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
static final class StreamExecution implements MongoQueryExecution {
|
||||
|
||||
private final @NonNull MongoOperations operations;
|
||||
private final @NonNull Converter<Object, Object> resultProcessing;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.repository.query.AbstractMongoQuery.Execution#execute(org.springframework.data.mongodb.core.query.Query, java.lang.Class, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object execute(Query query, Class<?> type, String collection) {
|
||||
|
||||
return StreamUtils.createStreamFromIterator((CloseableIterator<Object>) operations.stream(query, type))
|
||||
.map(new Function<Object, Object>() {
|
||||
|
||||
@Override
|
||||
public Object apply(Object t) {
|
||||
return resultProcessing.convert(t);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An {@link MongoQueryExecution} that wraps the results of the given delegate with the given result processing.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @since 1.9
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
static final class ResultProcessingExecution implements MongoQueryExecution {
|
||||
|
||||
private final @NonNull MongoQueryExecution delegate;
|
||||
private final @NonNull Converter<Object, Object> converter;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.repository.query.AbstractMongoQuery.Execution#execute(org.springframework.data.mongodb.core.query.Query, java.lang.Class, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public Object execute(Query query, Class<?> type, String collection) {
|
||||
return converter.convert(delegate.execute(query, type, collection));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link Converter} to post-process all source objects using the given {@link ResultProcessor}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @since 1.9
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
static final class ResultProcessingConverter implements Converter<Object, Object> {
|
||||
|
||||
private final @NonNull ResultProcessor processor;
|
||||
private final @NonNull MongoOperations operations;
|
||||
private final @NonNull EntityInstantiators instantiators;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public Object convert(Object source) {
|
||||
|
||||
ReturnedType returnedType = processor.getReturnedType();
|
||||
|
||||
if (ClassUtils.isPrimitiveOrWrapper(returnedType.getReturnedType())) {
|
||||
return source;
|
||||
}
|
||||
|
||||
Converter<Object, Object> converter = new DtoInstantiatingConverter(returnedType.getReturnedType(),
|
||||
operations.getConverter().getMappingContext(), instantiators);
|
||||
|
||||
return processor.processResult(source, converter);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2015 the original author or authors.
|
||||
* Copyright 2011-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -29,7 +29,6 @@ import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
import org.springframework.data.mongodb.repository.Meta;
|
||||
import org.springframework.data.mongodb.repository.Query;
|
||||
import org.springframework.data.projection.ProjectionFactory;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.query.QueryMethod;
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
@@ -57,15 +56,12 @@ public class MongoQueryMethod extends QueryMethod {
|
||||
/**
|
||||
* Creates a new {@link MongoQueryMethod} from the given {@link Method}.
|
||||
*
|
||||
* @param method must not be {@literal null}.
|
||||
* @param metadata must not be {@literal null}.
|
||||
* @param projectionFactory must not be {@literal null}.
|
||||
* @param mappingContext must not be {@literal null}.
|
||||
* @param method
|
||||
*/
|
||||
public MongoQueryMethod(Method method, RepositoryMetadata metadata, ProjectionFactory projectionFactory,
|
||||
public MongoQueryMethod(Method method, RepositoryMetadata metadata,
|
||||
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext) {
|
||||
|
||||
super(method, metadata, projectionFactory);
|
||||
super(method, metadata);
|
||||
|
||||
Assert.notNull(mappingContext, "MappingContext must not be null!");
|
||||
|
||||
@@ -136,8 +132,7 @@ public class MongoQueryMethod extends QueryMethod {
|
||||
|
||||
MongoPersistentEntity<?> returnedEntity = mappingContext.getPersistentEntity(returnedObjectType);
|
||||
MongoPersistentEntity<?> managedEntity = mappingContext.getPersistentEntity(domainClass);
|
||||
returnedEntity = returnedEntity == null || returnedEntity.getType().isInterface() ? managedEntity
|
||||
: returnedEntity;
|
||||
returnedEntity = returnedEntity == null ? managedEntity : returnedEntity;
|
||||
MongoPersistentEntity<?> collectionEntity = domainClass.isAssignableFrom(returnedObjectType) ? returnedEntity
|
||||
: managedEntity;
|
||||
|
||||
|
||||
@@ -20,13 +20,10 @@ import org.springframework.data.mongodb.core.MongoOperations;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
import org.springframework.data.mongodb.core.query.BasicQuery;
|
||||
import org.springframework.data.mongodb.core.query.Field;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.data.mongodb.core.query.TextCriteria;
|
||||
import org.springframework.data.repository.query.QueryMethod;
|
||||
import org.springframework.data.repository.query.RepositoryQuery;
|
||||
import org.springframework.data.repository.query.ResultProcessor;
|
||||
import org.springframework.data.repository.query.ReturnedType;
|
||||
import org.springframework.data.repository.query.parser.PartTree;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -37,27 +34,23 @@ import com.mongodb.util.JSONParseException;
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
* @author Thomas Darimont
|
||||
*/
|
||||
public class PartTreeMongoQuery extends AbstractMongoQuery {
|
||||
|
||||
private final PartTree tree;
|
||||
private final boolean isGeoNearQuery;
|
||||
private final MappingContext<?, MongoPersistentProperty> context;
|
||||
private final ResultProcessor processor;
|
||||
|
||||
/**
|
||||
* Creates a new {@link PartTreeMongoQuery} from the given {@link QueryMethod} and {@link MongoTemplate}.
|
||||
*
|
||||
* @param method must not be {@literal null}.
|
||||
* @param mongoOperations must not be {@literal null}.
|
||||
* @param template must not be {@literal null}.
|
||||
*/
|
||||
public PartTreeMongoQuery(MongoQueryMethod method, MongoOperations mongoOperations) {
|
||||
|
||||
super(method, mongoOperations);
|
||||
|
||||
this.processor = method.getResultProcessor();
|
||||
this.tree = new PartTree(method.getName(), processor.getReturnedType().getDomainType());
|
||||
this.tree = new PartTree(method.getName(), method.getEntityInformation().getJavaType());
|
||||
this.isGeoNearQuery = method.isGeoNearQuery();
|
||||
this.context = mongoOperations.getConverter().getMappingContext();
|
||||
}
|
||||
@@ -93,18 +86,6 @@ public class PartTreeMongoQuery extends AbstractMongoQuery {
|
||||
String fieldSpec = this.getQueryMethod().getFieldSpecification();
|
||||
|
||||
if (!StringUtils.hasText(fieldSpec)) {
|
||||
|
||||
ReturnedType returnedType = processor.withDynamicProjection(accessor).getReturnedType();
|
||||
|
||||
if (returnedType.isProjecting()) {
|
||||
|
||||
Field fields = query.fields();
|
||||
|
||||
for (String field : returnedType.getInputProperties()) {
|
||||
fields.include(field);
|
||||
}
|
||||
}
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,15 +21,14 @@ import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.xml.bind.DatatypeConverter;
|
||||
|
||||
import org.bson.BSON;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.mongodb.core.MongoOperations;
|
||||
import org.springframework.data.mongodb.core.query.BasicQuery;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.data.mongodb.repository.query.ExpressionEvaluatingParameterBinder.BindingContext;
|
||||
import org.springframework.data.repository.query.EvaluationContextProvider;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
@@ -47,7 +46,7 @@ public class StringBasedMongoQuery extends AbstractMongoQuery {
|
||||
|
||||
private static final String COUND_AND_DELETE = "Manually defined query for %s cannot be both a count and delete query at the same time!";
|
||||
private static final Logger LOG = LoggerFactory.getLogger(StringBasedMongoQuery.class);
|
||||
private static final ParameterBindingParser BINDING_PARSER = ParameterBindingParser.INSTANCE;
|
||||
private static final ParameterBindingParser PARSER = ParameterBindingParser.INSTANCE;
|
||||
|
||||
private final String query;
|
||||
private final String fieldSpec;
|
||||
@@ -55,45 +54,33 @@ public class StringBasedMongoQuery extends AbstractMongoQuery {
|
||||
private final boolean isDeleteQuery;
|
||||
private final List<ParameterBinding> queryParameterBindings;
|
||||
private final List<ParameterBinding> fieldSpecParameterBindings;
|
||||
private final ExpressionEvaluatingParameterBinder parameterBinder;
|
||||
|
||||
/**
|
||||
* Creates a new {@link StringBasedMongoQuery} for the given {@link MongoQueryMethod} and {@link MongoOperations}.
|
||||
*
|
||||
* @param method must not be {@literal null}.
|
||||
* @param mongoOperations must not be {@literal null}.
|
||||
* @param expressionParser must not be {@literal null}.
|
||||
* @param evaluationContextProvider must not be {@literal null}.
|
||||
*/
|
||||
public StringBasedMongoQuery(MongoQueryMethod method, MongoOperations mongoOperations,
|
||||
SpelExpressionParser expressionParser, EvaluationContextProvider evaluationContextProvider) {
|
||||
this(method.getAnnotatedQuery(), method, mongoOperations, expressionParser, evaluationContextProvider);
|
||||
public StringBasedMongoQuery(MongoQueryMethod method, MongoOperations mongoOperations) {
|
||||
this(method.getAnnotatedQuery(), method, mongoOperations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link StringBasedMongoQuery} for the given {@link String}, {@link MongoQueryMethod},
|
||||
* {@link MongoOperations}, {@link SpelExpressionParser} and {@link EvaluationContextProvider}.
|
||||
*
|
||||
* @param query must not be {@literal null}.
|
||||
* Creates a new {@link StringBasedMongoQuery} for the given {@link String}, {@link MongoQueryMethod} and
|
||||
* {@link MongoOperations}.
|
||||
*
|
||||
* @param method must not be {@literal null}.
|
||||
* @param mongoOperations must not be {@literal null}.
|
||||
* @param expressionParser must not be {@literal null}.
|
||||
* @param template must not be {@literal null}.
|
||||
*/
|
||||
public StringBasedMongoQuery(String query, MongoQueryMethod method, MongoOperations mongoOperations,
|
||||
SpelExpressionParser expressionParser, EvaluationContextProvider evaluationContextProvider) {
|
||||
public StringBasedMongoQuery(String query, MongoQueryMethod method, MongoOperations mongoOperations) {
|
||||
|
||||
super(method, mongoOperations);
|
||||
|
||||
Assert.notNull(query, "Query must not be null!");
|
||||
Assert.notNull(expressionParser, "SpelExpressionParser must not be null!");
|
||||
this.query = query;
|
||||
this.queryParameterBindings = PARSER.parseParameterBindingsFrom(query);
|
||||
|
||||
this.queryParameterBindings = new ArrayList<ParameterBinding>();
|
||||
this.query = BINDING_PARSER.parseAndCollectParameterBindingsFromQueryIntoBindings(query,
|
||||
this.queryParameterBindings);
|
||||
|
||||
this.fieldSpecParameterBindings = new ArrayList<ParameterBinding>();
|
||||
this.fieldSpec = BINDING_PARSER.parseAndCollectParameterBindingsFromQueryIntoBindings(
|
||||
method.getFieldSpecification(), this.fieldSpecParameterBindings);
|
||||
this.fieldSpec = method.getFieldSpecification();
|
||||
this.fieldSpecParameterBindings = PARSER.parseParameterBindingsFrom(method.getFieldSpecification());
|
||||
|
||||
this.isCountQuery = method.hasAnnotatedQuery() ? method.getQueryAnnotation().count() : false;
|
||||
this.isDeleteQuery = method.hasAnnotatedQuery() ? method.getQueryAnnotation().delete() : false;
|
||||
@@ -101,8 +88,6 @@ public class StringBasedMongoQuery extends AbstractMongoQuery {
|
||||
if (isCountQuery && isDeleteQuery) {
|
||||
throw new IllegalArgumentException(String.format(COUND_AND_DELETE, method));
|
||||
}
|
||||
|
||||
this.parameterBinder = new ExpressionEvaluatingParameterBinder(expressionParser, evaluationContextProvider);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -112,15 +97,21 @@ public class StringBasedMongoQuery extends AbstractMongoQuery {
|
||||
@Override
|
||||
protected Query createQuery(ConvertingParameterAccessor accessor) {
|
||||
|
||||
String queryString = parameterBinder.bind(this.query, accessor, new BindingContext(getQueryMethod()
|
||||
.getParameters(), queryParameterBindings));
|
||||
String fieldsString = parameterBinder.bind(this.fieldSpec, accessor, new BindingContext(getQueryMethod()
|
||||
.getParameters(), fieldSpecParameterBindings));
|
||||
String queryString = replacePlaceholders(query, accessor, queryParameterBindings);
|
||||
|
||||
Query query = new BasicQuery(queryString, fieldsString).with(accessor.getSort());
|
||||
Query query = null;
|
||||
|
||||
if (fieldSpec != null) {
|
||||
String fieldString = replacePlaceholders(fieldSpec, accessor, fieldSpecParameterBindings);
|
||||
query = new BasicQuery(queryString, fieldString);
|
||||
} else {
|
||||
query = new BasicQuery(queryString);
|
||||
}
|
||||
|
||||
query.with(accessor.getSort());
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug(String.format("Created query %s for %s fields.", query.getQueryObject(), query.getFieldsObject()));
|
||||
LOG.debug(String.format("Created query %s", query.getQueryObject()));
|
||||
}
|
||||
|
||||
return query;
|
||||
@@ -144,6 +135,62 @@ public class StringBasedMongoQuery extends AbstractMongoQuery {
|
||||
return this.isDeleteQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaced the parameter place-holders with the actual parameter values from the given {@link ParameterBinding}s.
|
||||
*
|
||||
* @param input
|
||||
* @param accessor
|
||||
* @param bindings
|
||||
* @return
|
||||
*/
|
||||
private String replacePlaceholders(String input, ConvertingParameterAccessor accessor, List<ParameterBinding> bindings) {
|
||||
|
||||
if (bindings.isEmpty()) {
|
||||
return input;
|
||||
}
|
||||
|
||||
StringBuilder result = new StringBuilder(input);
|
||||
|
||||
for (ParameterBinding binding : bindings) {
|
||||
|
||||
String parameter = binding.getParameter();
|
||||
int idx = result.indexOf(parameter);
|
||||
|
||||
if (idx != -1) {
|
||||
result.replace(idx, idx + parameter.length(), getParameterValueForBinding(accessor, binding));
|
||||
}
|
||||
}
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the serialized value to be used for the given {@link ParameterBinding}.
|
||||
*
|
||||
* @param accessor
|
||||
* @param binding
|
||||
* @return
|
||||
*/
|
||||
private String getParameterValueForBinding(ConvertingParameterAccessor accessor, ParameterBinding binding) {
|
||||
|
||||
Object value = accessor.getBindableValue(binding.getParameterIndex());
|
||||
|
||||
if (value instanceof String && binding.isQuoted()) {
|
||||
return (String) value;
|
||||
}
|
||||
|
||||
if (value instanceof byte[]) {
|
||||
|
||||
String base64representation = DatatypeConverter.printBase64Binary((byte[]) value);
|
||||
if (!binding.isQuoted()) {
|
||||
return "{ '$binary' : '" + base64representation + "', '$type' : " + BSON.B_GENERAL + "}";
|
||||
}
|
||||
return base64representation;
|
||||
}
|
||||
|
||||
return JSON.serialize(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* A parser that extracts the parameter bindings from a given query string.
|
||||
*
|
||||
@@ -153,12 +200,6 @@ public class StringBasedMongoQuery extends AbstractMongoQuery {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
private static final String EXPRESSION_PARAM_QUOTE = "'";
|
||||
private static final String EXPRESSION_PARAM_PREFIX = "?expr";
|
||||
private static final String INDEX_BASED_EXPRESSION_PARAM_START = "?#{";
|
||||
private static final String NAME_BASED_EXPRESSION_PARAM_START = ":#{";
|
||||
private static final char CURRLY_BRACE_OPEN = '{';
|
||||
private static final char CURRLY_BRACE_CLOSE = '}';
|
||||
private static final String PARAMETER_PREFIX = "_param_";
|
||||
private static final String PARSEABLE_PARAMETER = "\"" + PARAMETER_PREFIX + "$1\"";
|
||||
private static final Pattern PARAMETER_BINDING_PATTERN = Pattern.compile("\\?(\\d+)");
|
||||
@@ -170,84 +211,34 @@ public class StringBasedMongoQuery extends AbstractMongoQuery {
|
||||
* Returns a list of {@link ParameterBinding}s found in the given {@code input} or an
|
||||
* {@link Collections#emptyList()}.
|
||||
*
|
||||
* @param input can be {@literal null} or empty.
|
||||
* @param bindings must not be {@literal null}.
|
||||
* @param input
|
||||
* @param conversionService must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public String parseAndCollectParameterBindingsFromQueryIntoBindings(String input, List<ParameterBinding> bindings) {
|
||||
public List<ParameterBinding> parseParameterBindingsFrom(String input) {
|
||||
|
||||
if (!StringUtils.hasText(input)) {
|
||||
return input;
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
Assert.notNull(bindings, "Parameter bindings must not be null!");
|
||||
List<ParameterBinding> bindings = new ArrayList<ParameterBinding>();
|
||||
|
||||
String transformedInput = transformQueryAndCollectExpressionParametersIntoBindings(input, bindings);
|
||||
String parseableInput = makeParameterReferencesParseable(transformedInput);
|
||||
String parseableInput = makeParameterReferencesParseable(input);
|
||||
|
||||
collectParameterReferencesIntoBindings(bindings, JSON.parse(parseableInput));
|
||||
|
||||
return transformedInput;
|
||||
return bindings;
|
||||
}
|
||||
|
||||
private static String transformQueryAndCollectExpressionParametersIntoBindings(String input,
|
||||
List<ParameterBinding> bindings) {
|
||||
|
||||
StringBuilder result = new StringBuilder();
|
||||
|
||||
int startIndex = 0;
|
||||
int currentPos = 0;
|
||||
int exprIndex = 0;
|
||||
|
||||
while (currentPos < input.length()) {
|
||||
|
||||
int indexOfExpressionParameter = getIndexOfExpressionParameter(input, currentPos);
|
||||
|
||||
// no expression parameter found
|
||||
if (indexOfExpressionParameter < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
int exprStart = indexOfExpressionParameter + 3;
|
||||
currentPos = exprStart;
|
||||
|
||||
// eat parameter expression
|
||||
int curlyBraceOpenCnt = 1;
|
||||
|
||||
while (curlyBraceOpenCnt > 0) {
|
||||
switch (input.charAt(currentPos++)) {
|
||||
case CURRLY_BRACE_OPEN:
|
||||
curlyBraceOpenCnt++;
|
||||
break;
|
||||
case CURRLY_BRACE_CLOSE:
|
||||
curlyBraceOpenCnt--;
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
result.append(input.subSequence(startIndex, indexOfExpressionParameter));
|
||||
result.append(EXPRESSION_PARAM_QUOTE).append(EXPRESSION_PARAM_PREFIX);
|
||||
result.append(exprIndex);
|
||||
result.append(EXPRESSION_PARAM_QUOTE);
|
||||
|
||||
bindings.add(new ParameterBinding(exprIndex, true, input.substring(exprStart, currentPos - 1)));
|
||||
|
||||
startIndex = currentPos;
|
||||
|
||||
exprIndex++;
|
||||
}
|
||||
|
||||
return result.append(input.subSequence(currentPos, input.length())).toString();
|
||||
}
|
||||
|
||||
private static String makeParameterReferencesParseable(String input) {
|
||||
private String makeParameterReferencesParseable(String input) {
|
||||
|
||||
Matcher matcher = PARAMETER_BINDING_PATTERN.matcher(input);
|
||||
return matcher.replaceAll(PARSEABLE_PARAMETER);
|
||||
String parseableInput = matcher.replaceAll(PARSEABLE_PARAMETER);
|
||||
|
||||
return parseableInput;
|
||||
}
|
||||
|
||||
private static void collectParameterReferencesIntoBindings(List<ParameterBinding> bindings, Object value) {
|
||||
private void collectParameterReferencesIntoBindings(List<ParameterBinding> bindings, Object value) {
|
||||
|
||||
if (value instanceof String) {
|
||||
|
||||
@@ -257,10 +248,9 @@ public class StringBasedMongoQuery extends AbstractMongoQuery {
|
||||
} else if (value instanceof Pattern) {
|
||||
|
||||
String string = ((Pattern) value).toString().trim();
|
||||
|
||||
Matcher valueMatcher = PARSEABLE_BINDING_PATTERN.matcher(string);
|
||||
|
||||
while (valueMatcher.find()) {
|
||||
|
||||
int paramIndex = Integer.parseInt(valueMatcher.group(PARAMETER_INDEX_GROUP));
|
||||
|
||||
/*
|
||||
@@ -290,7 +280,7 @@ public class StringBasedMongoQuery extends AbstractMongoQuery {
|
||||
}
|
||||
}
|
||||
|
||||
private static void potentiallyAddBinding(String source, List<ParameterBinding> bindings) {
|
||||
private void potentiallyAddBinding(String source, List<ParameterBinding> bindings) {
|
||||
|
||||
Matcher valueMatcher = PARSEABLE_BINDING_PATTERN.matcher(source);
|
||||
|
||||
@@ -303,14 +293,6 @@ public class StringBasedMongoQuery extends AbstractMongoQuery {
|
||||
bindings.add(new ParameterBinding(paramIndex, quoted));
|
||||
}
|
||||
}
|
||||
|
||||
private static int getIndexOfExpressionParameter(String input, int position) {
|
||||
|
||||
int indexOfExpressionParameter = input.indexOf(INDEX_BASED_EXPRESSION_PARAM_START, position);
|
||||
|
||||
return indexOfExpressionParameter < 0 ? input.indexOf(NAME_BASED_EXPRESSION_PARAM_START, position)
|
||||
: indexOfExpressionParameter;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -318,11 +300,10 @@ public class StringBasedMongoQuery extends AbstractMongoQuery {
|
||||
*
|
||||
* @author Thomas Darimont
|
||||
*/
|
||||
static class ParameterBinding {
|
||||
private static class ParameterBinding {
|
||||
|
||||
private final int parameterIndex;
|
||||
private final boolean quoted;
|
||||
private final String expression;
|
||||
|
||||
/**
|
||||
* Creates a new {@link ParameterBinding} with the given {@code parameterIndex} and {@code quoted} information.
|
||||
@@ -331,14 +312,9 @@ public class StringBasedMongoQuery extends AbstractMongoQuery {
|
||||
* @param quoted whether or not the parameter is already quoted.
|
||||
*/
|
||||
public ParameterBinding(int parameterIndex, boolean quoted) {
|
||||
this(parameterIndex, quoted, null);
|
||||
}
|
||||
|
||||
public ParameterBinding(int parameterIndex, boolean quoted, String expression) {
|
||||
|
||||
this.parameterIndex = parameterIndex;
|
||||
this.quoted = quoted;
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
public boolean isQuoted() {
|
||||
@@ -350,15 +326,7 @@ public class StringBasedMongoQuery extends AbstractMongoQuery {
|
||||
}
|
||||
|
||||
public String getParameter() {
|
||||
return "?" + (isExpression() ? "expr" : "") + parameterIndex;
|
||||
}
|
||||
|
||||
public String getExpression() {
|
||||
return expression;
|
||||
}
|
||||
|
||||
public boolean isExpression() {
|
||||
return this.expression != null;
|
||||
return "?" + parameterIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2015 by the original author(s).
|
||||
* Copyright (c) 2011 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.
|
||||
@@ -17,7 +17,6 @@ package org.springframework.data.mongodb.repository.support;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.bson.types.ObjectId;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
import org.springframework.data.mongodb.repository.query.MongoEntityInformation;
|
||||
import org.springframework.data.repository.core.support.PersistentEntityInformation;
|
||||
@@ -28,14 +27,12 @@ import org.springframework.data.repository.core.support.PersistentEntityInformat
|
||||
* {@link MongoPersistentEntity} if given.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class MappingMongoEntityInformation<T, ID extends Serializable> extends PersistentEntityInformation<T, ID>
|
||||
implements MongoEntityInformation<T, ID> {
|
||||
|
||||
private final MongoPersistentEntity<T> entityMetadata;
|
||||
private final String customCollectionName;
|
||||
private final Class<ID> fallbackIdType;
|
||||
|
||||
/**
|
||||
* Creates a new {@link MappingMongoEntityInformation} for the given {@link MongoPersistentEntity}.
|
||||
@@ -43,18 +40,7 @@ public class MappingMongoEntityInformation<T, ID extends Serializable> extends P
|
||||
* @param entity must not be {@literal null}.
|
||||
*/
|
||||
public MappingMongoEntityInformation(MongoPersistentEntity<T> entity) {
|
||||
this(entity, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link MappingMongoEntityInformation} for the given {@link MongoPersistentEntity} and fallback
|
||||
* identifier type.
|
||||
*
|
||||
* @param entity must not be {@literal null}.
|
||||
* @param fallbackIdType can be {@literal null}.
|
||||
*/
|
||||
public MappingMongoEntityInformation(MongoPersistentEntity<T> entity, Class<ID> fallbackIdType) {
|
||||
this(entity, (String) null, fallbackIdType);
|
||||
this(entity, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,26 +51,11 @@ public class MappingMongoEntityInformation<T, ID extends Serializable> extends P
|
||||
* @param customCollectionName can be {@literal null}.
|
||||
*/
|
||||
public MappingMongoEntityInformation(MongoPersistentEntity<T> entity, String customCollectionName) {
|
||||
this(entity, customCollectionName, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link MappingMongoEntityInformation} for the given {@link MongoPersistentEntity}, collection name
|
||||
* and identifier type.
|
||||
*
|
||||
* @param entity must not be {@literal null}.
|
||||
* @param customCollectionName can be {@literal null}.
|
||||
* @param idType can be {@literal null}.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private MappingMongoEntityInformation(MongoPersistentEntity<T> entity, String customCollectionName,
|
||||
Class<ID> idType) {
|
||||
|
||||
super(entity);
|
||||
|
||||
this.entityMetadata = entity;
|
||||
this.customCollectionName = customCollectionName;
|
||||
this.fallbackIdType = idType != null ? idType : (Class<ID>) ObjectId.class;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
@@ -100,19 +71,4 @@ public class MappingMongoEntityInformation<T, ID extends Serializable> extends P
|
||||
public String getIdAttribute() {
|
||||
return entityMetadata.getIdProperty().getName();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.core.support.PersistentEntityInformation#getIdType()
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Class<ID> getIdType() {
|
||||
|
||||
if (this.entityMetadata.hasIdProperty()) {
|
||||
return super.getIdType();
|
||||
}
|
||||
|
||||
return fallbackIdType != null ? fallbackIdType : (Class<ID>) ObjectId.class;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2015 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.
|
||||
@@ -25,14 +25,14 @@ import javax.tools.Diagnostic;
|
||||
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
|
||||
import com.querydsl.apt.AbstractQuerydslProcessor;
|
||||
import com.querydsl.apt.Configuration;
|
||||
import com.querydsl.apt.DefaultConfiguration;
|
||||
import com.querydsl.core.annotations.QueryEmbeddable;
|
||||
import com.querydsl.core.annotations.QueryEmbedded;
|
||||
import com.querydsl.core.annotations.QueryEntities;
|
||||
import com.querydsl.core.annotations.QuerySupertype;
|
||||
import com.querydsl.core.annotations.QueryTransient;
|
||||
import com.mysema.query.annotations.QueryEmbeddable;
|
||||
import com.mysema.query.annotations.QueryEmbedded;
|
||||
import com.mysema.query.annotations.QueryEntities;
|
||||
import com.mysema.query.annotations.QuerySupertype;
|
||||
import com.mysema.query.annotations.QueryTransient;
|
||||
import com.mysema.query.apt.AbstractQuerydslProcessor;
|
||||
import com.mysema.query.apt.Configuration;
|
||||
import com.mysema.query.apt.DefaultConfiguration;
|
||||
|
||||
/**
|
||||
* Annotation processor to create Querydsl query types for QueryDsl annotated classes.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.
|
||||
@@ -30,43 +30,34 @@ import org.springframework.data.mongodb.repository.query.MongoEntityInformation;
|
||||
import org.springframework.data.mongodb.repository.query.MongoQueryMethod;
|
||||
import org.springframework.data.mongodb.repository.query.PartTreeMongoQuery;
|
||||
import org.springframework.data.mongodb.repository.query.StringBasedMongoQuery;
|
||||
import org.springframework.data.projection.ProjectionFactory;
|
||||
import org.springframework.data.querydsl.QueryDslPredicateExecutor;
|
||||
import org.springframework.data.repository.core.NamedQueries;
|
||||
import org.springframework.data.repository.core.RepositoryInformation;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
|
||||
import org.springframework.data.repository.query.EvaluationContextProvider;
|
||||
import org.springframework.data.repository.query.QueryLookupStrategy;
|
||||
import org.springframework.data.repository.query.QueryLookupStrategy.Key;
|
||||
import org.springframework.data.repository.query.RepositoryQuery;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Factory to create {@link MongoRepository} instances.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Darimont
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class MongoRepositoryFactory extends RepositoryFactorySupport {
|
||||
|
||||
private static final SpelExpressionParser EXPRESSION_PARSER = new SpelExpressionParser();
|
||||
|
||||
private final MongoOperations operations;
|
||||
private final MongoOperations mongoOperations;
|
||||
private final MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
|
||||
|
||||
/**
|
||||
* Creates a new {@link MongoRepositoryFactory} with the given {@link MongoOperations}.
|
||||
*
|
||||
* @param mongoOperations must not be {@literal null}.
|
||||
* @param mongoOperations must not be {@literal null}
|
||||
*/
|
||||
public MongoRepositoryFactory(MongoOperations mongoOperations) {
|
||||
|
||||
Assert.notNull(mongoOperations);
|
||||
|
||||
this.operations = mongoOperations;
|
||||
this.mongoOperations = mongoOperations;
|
||||
this.mappingContext = mongoOperations.getConverter().getMappingContext();
|
||||
}
|
||||
|
||||
@@ -76,97 +67,84 @@ public class MongoRepositoryFactory extends RepositoryFactorySupport {
|
||||
*/
|
||||
@Override
|
||||
protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
|
||||
|
||||
boolean isQueryDslRepository = QUERY_DSL_PRESENT
|
||||
&& QueryDslPredicateExecutor.class.isAssignableFrom(metadata.getRepositoryInterface());
|
||||
|
||||
return isQueryDslRepository ? QueryDslMongoRepository.class : SimpleMongoRepository.class;
|
||||
return isQueryDslRepository(metadata.getRepositoryInterface()) ? QueryDslMongoRepository.class
|
||||
: SimpleMongoRepository.class;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.core.support.RepositoryFactorySupport#getTargetRepository(org.springframework.data.repository.core.RepositoryInformation)
|
||||
* @see org.springframework.data.repository.core.support.RepositoryFactorySupport#getTargetRepository(org.springframework.data.repository.core.RepositoryMetadata)
|
||||
*/
|
||||
@Override
|
||||
protected Object getTargetRepository(RepositoryInformation information) {
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
protected Object getTargetRepository(RepositoryMetadata metadata) {
|
||||
|
||||
MongoEntityInformation<?, Serializable> entityInformation = getEntityInformation(information.getDomainType(),
|
||||
information);
|
||||
return getTargetRepositoryViaReflection(information, entityInformation, operations);
|
||||
}
|
||||
Class<?> repositoryInterface = metadata.getRepositoryInterface();
|
||||
MongoEntityInformation<?, Serializable> entityInformation = getEntityInformation(metadata.getDomainType());
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.core.support.RepositoryFactorySupport#getQueryLookupStrategy(org.springframework.data.repository.query.QueryLookupStrategy.Key, org.springframework.data.repository.query.EvaluationContextProvider)
|
||||
*/
|
||||
@Override
|
||||
protected QueryLookupStrategy getQueryLookupStrategy(Key key, EvaluationContextProvider evaluationContextProvider) {
|
||||
return new MongoQueryLookupStrategy(operations, evaluationContextProvider, mappingContext);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.core.support.RepositoryFactorySupport#getEntityInformation(java.lang.Class)
|
||||
*/
|
||||
public <T, ID extends Serializable> MongoEntityInformation<T, ID> getEntityInformation(Class<T> domainClass) {
|
||||
return getEntityInformation(domainClass, null);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T, ID extends Serializable> MongoEntityInformation<T, ID> getEntityInformation(Class<T> domainClass,
|
||||
RepositoryInformation information) {
|
||||
|
||||
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(domainClass);
|
||||
|
||||
if (entity == null) {
|
||||
throw new MappingException(
|
||||
String.format("Could not lookup mapping metadata for domain class %s!", domainClass.getName()));
|
||||
if (isQueryDslRepository(repositoryInterface)) {
|
||||
return new QueryDslMongoRepository(entityInformation, mongoOperations);
|
||||
} else {
|
||||
return new SimpleMongoRepository(entityInformation, mongoOperations);
|
||||
}
|
||||
}
|
||||
|
||||
return new MappingMongoEntityInformation<T, ID>((MongoPersistentEntity<T>) entity,
|
||||
information != null ? (Class<ID>) information.getIdType() : null);
|
||||
private static boolean isQueryDslRepository(Class<?> repositoryInterface) {
|
||||
|
||||
return QUERY_DSL_PRESENT && QueryDslPredicateExecutor.class.isAssignableFrom(repositoryInterface);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.core.support.RepositoryFactorySupport#getQueryLookupStrategy(org.springframework.data.repository.query.QueryLookupStrategy.Key)
|
||||
*/
|
||||
@Override
|
||||
protected QueryLookupStrategy getQueryLookupStrategy(Key key) {
|
||||
return new MongoQueryLookupStrategy();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link QueryLookupStrategy} to create {@link PartTreeMongoQuery} instances.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Darimont
|
||||
*/
|
||||
private static class MongoQueryLookupStrategy implements QueryLookupStrategy {
|
||||
private class MongoQueryLookupStrategy implements QueryLookupStrategy {
|
||||
|
||||
private final MongoOperations operations;
|
||||
private final EvaluationContextProvider evaluationContextProvider;
|
||||
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
|
||||
|
||||
public MongoQueryLookupStrategy(MongoOperations operations, EvaluationContextProvider evaluationContextProvider,
|
||||
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext) {
|
||||
|
||||
this.operations = operations;
|
||||
this.evaluationContextProvider = evaluationContextProvider;
|
||||
this.mappingContext = mappingContext;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.query.QueryLookupStrategy#resolveQuery(java.lang.reflect.Method, org.springframework.data.repository.core.RepositoryMetadata, org.springframework.data.projection.ProjectionFactory, org.springframework.data.repository.core.NamedQueries)
|
||||
* @see org.springframework.data.repository.query.QueryLookupStrategy#resolveQuery(java.lang.reflect.Method, org.springframework.data.repository.core.RepositoryMetadata, org.springframework.data.repository.core.NamedQueries)
|
||||
*/
|
||||
@Override
|
||||
public RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, ProjectionFactory factory,
|
||||
NamedQueries namedQueries) {
|
||||
public RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, NamedQueries namedQueries) {
|
||||
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, factory, mappingContext);
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, mappingContext);
|
||||
String namedQueryName = queryMethod.getNamedQueryName();
|
||||
|
||||
if (namedQueries.hasQuery(namedQueryName)) {
|
||||
String namedQuery = namedQueries.getQuery(namedQueryName);
|
||||
return new StringBasedMongoQuery(namedQuery, queryMethod, operations, EXPRESSION_PARSER,
|
||||
evaluationContextProvider);
|
||||
return new StringBasedMongoQuery(namedQuery, queryMethod, mongoOperations);
|
||||
} else if (queryMethod.hasAnnotatedQuery()) {
|
||||
return new StringBasedMongoQuery(queryMethod, operations, EXPRESSION_PARSER, evaluationContextProvider);
|
||||
return new StringBasedMongoQuery(queryMethod, mongoOperations);
|
||||
} else {
|
||||
return new PartTreeMongoQuery(queryMethod, operations);
|
||||
return new PartTreeMongoQuery(queryMethod, mongoOperations);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @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) {
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,12 +34,12 @@ import org.springframework.data.repository.core.EntityInformation;
|
||||
import org.springframework.data.repository.core.EntityMetadata;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.querydsl.core.types.EntityPath;
|
||||
import com.querydsl.core.types.Expression;
|
||||
import com.querydsl.core.types.OrderSpecifier;
|
||||
import com.querydsl.core.types.Predicate;
|
||||
import com.querydsl.core.types.dsl.PathBuilder;
|
||||
import com.querydsl.mongodb.AbstractMongodbQuery;
|
||||
import com.mysema.query.mongodb.MongodbQuery;
|
||||
import com.mysema.query.types.EntityPath;
|
||||
import com.mysema.query.types.Expression;
|
||||
import com.mysema.query.types.OrderSpecifier;
|
||||
import com.mysema.query.types.Predicate;
|
||||
import com.mysema.query.types.path.PathBuilder;
|
||||
|
||||
/**
|
||||
* Special QueryDsl based repository implementation that allows execution {@link Predicate}s in various forms.
|
||||
@@ -47,8 +47,8 @@ import com.querydsl.mongodb.AbstractMongodbQuery;
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Darimont
|
||||
*/
|
||||
public class QueryDslMongoRepository<T, ID extends Serializable> extends SimpleMongoRepository<T, ID>
|
||||
implements QueryDslPredicateExecutor<T> {
|
||||
public class QueryDslMongoRepository<T, ID extends Serializable> extends SimpleMongoRepository<T, ID> implements
|
||||
QueryDslPredicateExecutor<T> {
|
||||
|
||||
private final PathBuilder<T> builder;
|
||||
private final EntityInformation<T, ID> entityInformation;
|
||||
@@ -92,7 +92,7 @@ public class QueryDslMongoRepository<T, ID extends Serializable> extends SimpleM
|
||||
*/
|
||||
@Override
|
||||
public T findOne(Predicate predicate) {
|
||||
return createQueryFor(predicate).fetchOne();
|
||||
return createQueryFor(predicate).uniqueResult();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -101,7 +101,7 @@ public class QueryDslMongoRepository<T, ID extends Serializable> extends SimpleM
|
||||
*/
|
||||
@Override
|
||||
public List<T> findAll(Predicate predicate) {
|
||||
return createQueryFor(predicate).fetchResults().getResults();
|
||||
return createQueryFor(predicate).list();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -110,7 +110,7 @@ public class QueryDslMongoRepository<T, ID extends Serializable> extends SimpleM
|
||||
*/
|
||||
@Override
|
||||
public List<T> findAll(Predicate predicate, OrderSpecifier<?>... orders) {
|
||||
return createQueryFor(predicate).orderBy(orders).fetchResults().getResults();
|
||||
return createQueryFor(predicate).orderBy(orders).list();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -119,7 +119,7 @@ public class QueryDslMongoRepository<T, ID extends Serializable> extends SimpleM
|
||||
*/
|
||||
@Override
|
||||
public List<T> findAll(Predicate predicate, Sort sort) {
|
||||
return applySorting(createQueryFor(predicate), sort).fetchResults().getResults();
|
||||
return applySorting(createQueryFor(predicate), sort).list();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -128,7 +128,7 @@ public class QueryDslMongoRepository<T, ID extends Serializable> extends SimpleM
|
||||
*/
|
||||
@Override
|
||||
public Iterable<T> findAll(OrderSpecifier<?>... orders) {
|
||||
return createQuery().orderBy(orders).fetchResults().getResults();
|
||||
return createQuery().orderBy(orders).list();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -138,11 +138,10 @@ public class QueryDslMongoRepository<T, ID extends Serializable> extends SimpleM
|
||||
@Override
|
||||
public Page<T> findAll(Predicate predicate, Pageable pageable) {
|
||||
|
||||
AbstractMongodbQuery<T, SpringDataMongodbQuery<T>> countQuery = createQueryFor(predicate);
|
||||
AbstractMongodbQuery<T, SpringDataMongodbQuery<T>> query = createQueryFor(predicate);
|
||||
MongodbQuery<T> countQuery = createQueryFor(predicate);
|
||||
MongodbQuery<T> query = createQueryFor(predicate);
|
||||
|
||||
return new PageImpl<T>(applyPagination(query, pageable).fetchResults().getResults(), pageable,
|
||||
countQuery.fetchCount());
|
||||
return new PageImpl<T>(applyPagination(query, pageable).list(), pageable, countQuery.count());
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -152,11 +151,10 @@ public class QueryDslMongoRepository<T, ID extends Serializable> extends SimpleM
|
||||
@Override
|
||||
public Page<T> findAll(Pageable pageable) {
|
||||
|
||||
AbstractMongodbQuery<T, SpringDataMongodbQuery<T>> countQuery = createQuery();
|
||||
AbstractMongodbQuery<T, SpringDataMongodbQuery<T>> query = createQuery();
|
||||
MongodbQuery<T> countQuery = createQuery();
|
||||
MongodbQuery<T> query = createQuery();
|
||||
|
||||
return new PageImpl<T>(applyPagination(query, pageable).fetchResults().getResults(), pageable,
|
||||
countQuery.fetchCount());
|
||||
return new PageImpl<T>(applyPagination(query, pageable).list(), pageable, countQuery.count());
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -165,7 +163,7 @@ public class QueryDslMongoRepository<T, ID extends Serializable> extends SimpleM
|
||||
*/
|
||||
@Override
|
||||
public List<T> findAll(Sort sort) {
|
||||
return applySorting(createQuery(), sort).fetchResults().getResults();
|
||||
return applySorting(createQuery(), sort).list();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -174,7 +172,7 @@ public class QueryDslMongoRepository<T, ID extends Serializable> extends SimpleM
|
||||
*/
|
||||
@Override
|
||||
public long count(Predicate predicate) {
|
||||
return createQueryFor(predicate).fetchCount();
|
||||
return createQueryFor(predicate).count();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -183,7 +181,7 @@ public class QueryDslMongoRepository<T, ID extends Serializable> extends SimpleM
|
||||
*/
|
||||
@Override
|
||||
public boolean exists(Predicate predicate) {
|
||||
return createQueryFor(predicate).fetchCount() > 0;
|
||||
return createQueryFor(predicate).exists();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -192,7 +190,7 @@ public class QueryDslMongoRepository<T, ID extends Serializable> extends SimpleM
|
||||
* @param predicate
|
||||
* @return
|
||||
*/
|
||||
private AbstractMongodbQuery<T, SpringDataMongodbQuery<T>> createQueryFor(Predicate predicate) {
|
||||
private MongodbQuery<T> createQueryFor(Predicate predicate) {
|
||||
return createQuery().where(predicate);
|
||||
}
|
||||
|
||||
@@ -201,7 +199,7 @@ public class QueryDslMongoRepository<T, ID extends Serializable> extends SimpleM
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private AbstractMongodbQuery<T, SpringDataMongodbQuery<T>> createQuery() {
|
||||
private MongodbQuery<T> createQuery() {
|
||||
return new SpringDataMongodbQuery<T>(mongoOperations, entityInformation.getJavaType());
|
||||
}
|
||||
|
||||
@@ -212,8 +210,7 @@ public class QueryDslMongoRepository<T, ID extends Serializable> extends SimpleM
|
||||
* @param pageable
|
||||
* @return
|
||||
*/
|
||||
private AbstractMongodbQuery<T, SpringDataMongodbQuery<T>> applyPagination(
|
||||
AbstractMongodbQuery<T, SpringDataMongodbQuery<T>> query, Pageable pageable) {
|
||||
private MongodbQuery<T> applyPagination(MongodbQuery<T> query, Pageable pageable) {
|
||||
|
||||
if (pageable == null) {
|
||||
return query;
|
||||
@@ -230,8 +227,7 @@ public class QueryDslMongoRepository<T, ID extends Serializable> extends SimpleM
|
||||
* @param sort
|
||||
* @return
|
||||
*/
|
||||
private AbstractMongodbQuery<T, SpringDataMongodbQuery<T>> applySorting(
|
||||
AbstractMongodbQuery<T, SpringDataMongodbQuery<T>> query, Sort sort) {
|
||||
private MongodbQuery<T> applySorting(MongodbQuery<T> query, Sort sort) {
|
||||
|
||||
if (sort == null) {
|
||||
return query;
|
||||
@@ -264,7 +260,7 @@ public class QueryDslMongoRepository<T, ID extends Serializable> extends SimpleM
|
||||
|
||||
Expression<Object> property = builder.get(order.getProperty());
|
||||
|
||||
return new OrderSpecifier(
|
||||
order.isAscending() ? com.querydsl.core.types.Order.ASC : com.querydsl.core.types.Order.DESC, property);
|
||||
return new OrderSpecifier(order.isAscending() ? com.mysema.query.types.Order.ASC
|
||||
: com.mysema.query.types.Order.DESC, property);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2015 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 @@ import org.springframework.data.mongodb.core.MongoOperations;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.querydsl.core.types.EntityPath;
|
||||
import com.querydsl.mongodb.AbstractMongodbQuery;
|
||||
import com.mysema.query.mongodb.MongodbQuery;
|
||||
import com.mysema.query.types.EntityPath;
|
||||
|
||||
/**
|
||||
* Base class to create repository implementations based on Querydsl.
|
||||
@@ -36,7 +36,7 @@ public abstract class QuerydslRepositorySupport {
|
||||
/**
|
||||
* Creates a new {@link QuerydslRepositorySupport} for the given {@link MongoOperations}.
|
||||
*
|
||||
* @param operations must not be {@literal null}.
|
||||
* @param operations must not be {@literal null}
|
||||
*/
|
||||
public QuerydslRepositorySupport(MongoOperations operations) {
|
||||
|
||||
@@ -53,7 +53,7 @@ public abstract class QuerydslRepositorySupport {
|
||||
* @param path
|
||||
* @return
|
||||
*/
|
||||
protected <T> AbstractMongodbQuery<T, SpringDataMongodbQuery<T>> from(final EntityPath<T> path) {
|
||||
protected <T> MongodbQuery<T> from(final EntityPath<T> path) {
|
||||
Assert.notNull(path);
|
||||
MongoPersistentEntity<?> entity = context.getPersistentEntity(path.getType());
|
||||
return from(path, entity.getCollection());
|
||||
@@ -66,7 +66,7 @@ public abstract class QuerydslRepositorySupport {
|
||||
* @param collection must not be blank or {@literal null}
|
||||
* @return
|
||||
*/
|
||||
protected <T> AbstractMongodbQuery<T, SpringDataMongodbQuery<T>> from(final EntityPath<T> path, String collection) {
|
||||
protected <T> MongodbQuery<T> from(final EntityPath<T> path, String collection) {
|
||||
|
||||
Assert.notNull(path);
|
||||
Assert.hasText(collection);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2015 the original author or authors.
|
||||
* 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.
|
||||
@@ -20,14 +20,14 @@ import org.springframework.data.mongodb.core.MongoOperations;
|
||||
import com.google.common.base.Function;
|
||||
import com.mongodb.DBCollection;
|
||||
import com.mongodb.DBObject;
|
||||
import com.querydsl.mongodb.AbstractMongodbQuery;
|
||||
import com.mysema.query.mongodb.MongodbQuery;
|
||||
|
||||
/**
|
||||
* Spring Data specific {@link MongodbQuery} implementation.
|
||||
* Spring Data specfic {@link MongodbQuery} implementation.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
class SpringDataMongodbQuery<T> extends AbstractMongodbQuery<T, SpringDataMongodbQuery<T>> {
|
||||
class SpringDataMongodbQuery<T> extends MongodbQuery<T> {
|
||||
|
||||
private final MongoOperations operations;
|
||||
|
||||
@@ -48,8 +48,7 @@ class SpringDataMongodbQuery<T> extends AbstractMongodbQuery<T, SpringDataMongod
|
||||
* @param type must not be {@literal null}.
|
||||
* @param collectionName must not be {@literal null} or empty.
|
||||
*/
|
||||
public SpringDataMongodbQuery(final MongoOperations operations, final Class<? extends T> type,
|
||||
String collectionName) {
|
||||
public SpringDataMongodbQuery(final MongoOperations operations, final Class<? extends T> type, String collectionName) {
|
||||
|
||||
super(operations.getCollection(collectionName), new Function<DBObject, T>() {
|
||||
public T apply(DBObject input) {
|
||||
@@ -62,7 +61,7 @@ class SpringDataMongodbQuery<T> extends AbstractMongodbQuery<T, SpringDataMongod
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see com.querydsl.mongodb.AbstractMongodbQuery#getCollection(java.lang.Class)
|
||||
* @see com.mysema.query.mongodb.MongodbQuery#getCollection(java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
protected DBCollection getCollection(Class<?> type) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2015 the original author or authors.
|
||||
* Copyright 2011-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -29,10 +29,12 @@ import org.springframework.util.Assert;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.DBRef;
|
||||
import com.querydsl.core.types.Path;
|
||||
import com.querydsl.core.types.PathMetadata;
|
||||
import com.querydsl.core.types.PathType;
|
||||
import com.querydsl.mongodb.MongodbSerializer;
|
||||
import com.mysema.query.mongodb.MongodbSerializer;
|
||||
import com.mysema.query.types.Constant;
|
||||
import com.mysema.query.types.Operation;
|
||||
import com.mysema.query.types.Path;
|
||||
import com.mysema.query.types.PathMetadata;
|
||||
import com.mysema.query.types.PathType;
|
||||
|
||||
/**
|
||||
* Custom {@link MongodbSerializer} to take mapping information into account when building keys for constraints.
|
||||
@@ -74,10 +76,10 @@ class SpringDataMongodbSerializer extends MongodbSerializer {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see com.querydsl.mongodb.MongodbSerializer#getKeyForPath(com.querydsl.core.types.Path, com.querydsl.core.types.PathMetadata)
|
||||
* @see com.mysema.query.mongodb.MongodbSerializer#getKeyForPath(com.mysema.query.types.Path, com.mysema.query.types.PathMetadata)
|
||||
*/
|
||||
@Override
|
||||
protected String getKeyForPath(Path<?> expr, PathMetadata metadata) {
|
||||
protected String getKeyForPath(Path<?> expr, PathMetadata<?> metadata) {
|
||||
|
||||
if (!metadata.getPathType().equals(PathType.PROPERTY)) {
|
||||
return super.getKeyForPath(expr, metadata);
|
||||
@@ -92,7 +94,7 @@ class SpringDataMongodbSerializer extends MongodbSerializer {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see com.querydsl.mongodb.MongodbSerializer#asDBObject(java.lang.String, java.lang.Object)
|
||||
* @see com.mysema.query.mongodb.MongodbSerializer#asDBObject(java.lang.String, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
protected DBObject asDBObject(String key, Object value) {
|
||||
@@ -106,7 +108,7 @@ class SpringDataMongodbSerializer extends MongodbSerializer {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see com.querydsl.mongodb.MongodbSerializer#isReference(com.querydsl.core.types.Path)
|
||||
* @see com.mysema.query.mongodb.MongodbSerializer#isReference(com.mysema.query.types.Path)
|
||||
*/
|
||||
@Override
|
||||
protected boolean isReference(Path<?> path) {
|
||||
@@ -117,13 +119,34 @@ class SpringDataMongodbSerializer extends MongodbSerializer {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see com.querydsl.mongodb.MongodbSerializer#asReference(java.lang.Object)
|
||||
* @see com.mysema.query.mongodb.MongodbSerializer#asReference(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
protected DBRef asReference(Object constant) {
|
||||
return converter.toDBRef(constant, null);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see com.mysema.query.mongodb.MongodbSerializer#asReference(com.mysema.query.types.Operation, int)
|
||||
*/
|
||||
@Override
|
||||
protected DBRef asReference(Operation<?> expr, int constIndex) {
|
||||
|
||||
for (Object arg : expr.getArgs()) {
|
||||
|
||||
if (arg instanceof Path) {
|
||||
|
||||
MongoPersistentProperty property = getPropertyFor((Path<?>) arg);
|
||||
Object constant = ((Constant<?>) expr.getArg(constIndex)).getConstant();
|
||||
|
||||
return converter.toDBRef(constant, property);
|
||||
}
|
||||
}
|
||||
|
||||
return super.asReference(expr, constIndex);
|
||||
}
|
||||
|
||||
private MongoPersistentProperty getPropertyFor(Path<?> path) {
|
||||
|
||||
Path<?> parent = path.getMetadata().getParent();
|
||||
|
||||
@@ -1,140 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 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.util;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* {@link MongoDbErrorCodes} holds MongoDB specific error codes outlined in {@literal mongo/base/error_codes.err}.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @since 1.8
|
||||
*/
|
||||
public final class MongoDbErrorCodes {
|
||||
|
||||
static HashMap<Integer, String> dataAccessResourceFailureCodes;
|
||||
static HashMap<Integer, String> dataIntegrityViolationCodes;
|
||||
static HashMap<Integer, String> duplicateKeyCodes;
|
||||
static HashMap<Integer, String> invalidDataAccessApiUsageExeption;
|
||||
static HashMap<Integer, String> permissionDeniedCodes;
|
||||
|
||||
static HashMap<Integer, String> errorCodes;
|
||||
|
||||
static {
|
||||
|
||||
dataAccessResourceFailureCodes = new HashMap<Integer, String>(10);
|
||||
dataAccessResourceFailureCodes.put(6, "HostUnreachable");
|
||||
dataAccessResourceFailureCodes.put(7, "HostNotFound");
|
||||
dataAccessResourceFailureCodes.put(89, "NetworkTimeout");
|
||||
dataAccessResourceFailureCodes.put(91, "ShutdownInProgress");
|
||||
dataAccessResourceFailureCodes.put(12000, "SlaveDelayDifferential");
|
||||
dataAccessResourceFailureCodes.put(10084, "CannotFindMapFile64Bit");
|
||||
dataAccessResourceFailureCodes.put(10085, "CannotFindMapFile");
|
||||
dataAccessResourceFailureCodes.put(10357, "ShutdownInProgress");
|
||||
dataAccessResourceFailureCodes.put(10359, "Header==0");
|
||||
dataAccessResourceFailureCodes.put(13440, "BadOffsetInFile");
|
||||
dataAccessResourceFailureCodes.put(13441, "BadOffsetInFile");
|
||||
dataAccessResourceFailureCodes.put(13640, "DataFileHeaderCorrupt");
|
||||
|
||||
dataIntegrityViolationCodes = new HashMap<Integer, String>(6);
|
||||
dataIntegrityViolationCodes.put(67, "CannotCreateIndex");
|
||||
dataIntegrityViolationCodes.put(68, "IndexAlreadyExists");
|
||||
dataIntegrityViolationCodes.put(85, "IndexOptionsConflict");
|
||||
dataIntegrityViolationCodes.put(86, "IndexKeySpecsConflict");
|
||||
dataIntegrityViolationCodes.put(112, "WriteConflict");
|
||||
dataIntegrityViolationCodes.put(117, "ConflictingOperationInProgress");
|
||||
|
||||
duplicateKeyCodes = new HashMap<Integer, String>(3);
|
||||
duplicateKeyCodes.put(3, "OBSOLETE_DuplicateKey");
|
||||
duplicateKeyCodes.put(84, "DuplicateKeyValue");
|
||||
duplicateKeyCodes.put(11000, "DuplicateKey");
|
||||
duplicateKeyCodes.put(11001, "DuplicateKey");
|
||||
|
||||
invalidDataAccessApiUsageExeption = new HashMap<Integer, String>();
|
||||
invalidDataAccessApiUsageExeption.put(5, "GraphContainsCycle");
|
||||
invalidDataAccessApiUsageExeption.put(9, "FailedToParse");
|
||||
invalidDataAccessApiUsageExeption.put(14, "TypeMismatch");
|
||||
invalidDataAccessApiUsageExeption.put(15, "Overflow");
|
||||
invalidDataAccessApiUsageExeption.put(16, "InvalidLength");
|
||||
invalidDataAccessApiUsageExeption.put(20, "IllegalOperation");
|
||||
invalidDataAccessApiUsageExeption.put(21, "EmptyArrayOperation");
|
||||
invalidDataAccessApiUsageExeption.put(22, "InvalidBSON");
|
||||
invalidDataAccessApiUsageExeption.put(23, "AlreadyInitialized");
|
||||
invalidDataAccessApiUsageExeption.put(29, "NonExistentPath");
|
||||
invalidDataAccessApiUsageExeption.put(30, "InvalidPath");
|
||||
invalidDataAccessApiUsageExeption.put(40, "ConflictingUpdateOperators");
|
||||
invalidDataAccessApiUsageExeption.put(45, "UserDataInconsistent");
|
||||
invalidDataAccessApiUsageExeption.put(30, "DollarPrefixedFieldName");
|
||||
invalidDataAccessApiUsageExeption.put(52, "InvalidPath");
|
||||
invalidDataAccessApiUsageExeption.put(53, "InvalidIdField");
|
||||
invalidDataAccessApiUsageExeption.put(54, "NotSingleValueField");
|
||||
invalidDataAccessApiUsageExeption.put(55, "InvalidDBRef");
|
||||
invalidDataAccessApiUsageExeption.put(56, "EmptyFieldName");
|
||||
invalidDataAccessApiUsageExeption.put(57, "DottedFieldName");
|
||||
invalidDataAccessApiUsageExeption.put(59, "CommandNotFound");
|
||||
invalidDataAccessApiUsageExeption.put(60, "DatabaseNotFound");
|
||||
invalidDataAccessApiUsageExeption.put(61, "ShardKeyNotFound");
|
||||
invalidDataAccessApiUsageExeption.put(62, "OplogOperationUnsupported");
|
||||
invalidDataAccessApiUsageExeption.put(66, "ImmutableField");
|
||||
invalidDataAccessApiUsageExeption.put(72, "InvalidOptions");
|
||||
invalidDataAccessApiUsageExeption.put(115, "CommandNotSupported");
|
||||
invalidDataAccessApiUsageExeption.put(116, "DocTooLargeForCapped");
|
||||
invalidDataAccessApiUsageExeption.put(130, "SymbolNotFound");
|
||||
invalidDataAccessApiUsageExeption.put(17280, "KeyTooLong");
|
||||
invalidDataAccessApiUsageExeption.put(13334, "ShardKeyTooBig");
|
||||
|
||||
permissionDeniedCodes = new HashMap<Integer, String>();
|
||||
permissionDeniedCodes.put(11, "UserNotFound");
|
||||
permissionDeniedCodes.put(18, "AuthenticationFailed");
|
||||
permissionDeniedCodes.put(31, "RoleNotFound");
|
||||
permissionDeniedCodes.put(32, "RolesNotRelated");
|
||||
permissionDeniedCodes.put(33, "PrvilegeNotFound");
|
||||
permissionDeniedCodes.put(15847, "CannotAuthenticate");
|
||||
permissionDeniedCodes.put(16704, "CannotAuthenticateToAdminDB");
|
||||
permissionDeniedCodes.put(16705, "CannotAuthenticateToAdminDB");
|
||||
|
||||
errorCodes = new HashMap<Integer, String>();
|
||||
errorCodes.putAll(dataAccessResourceFailureCodes);
|
||||
errorCodes.putAll(dataIntegrityViolationCodes);
|
||||
errorCodes.putAll(duplicateKeyCodes);
|
||||
errorCodes.putAll(invalidDataAccessApiUsageExeption);
|
||||
errorCodes.putAll(permissionDeniedCodes);
|
||||
}
|
||||
|
||||
public static boolean isDataIntegrityViolationCode(Integer errorCode) {
|
||||
return errorCode == null ? false : dataIntegrityViolationCodes.containsKey(errorCode);
|
||||
}
|
||||
|
||||
public static boolean isDataAccessResourceFailureCode(Integer errorCode) {
|
||||
return errorCode == null ? false : dataAccessResourceFailureCodes.containsKey(errorCode);
|
||||
}
|
||||
|
||||
public static boolean isDuplicateKeyCode(Integer errorCode) {
|
||||
return errorCode == null ? false : duplicateKeyCodes.containsKey(errorCode);
|
||||
}
|
||||
|
||||
public static boolean isPermissionDeniedCode(Integer errorCode) {
|
||||
return errorCode == null ? false : permissionDeniedCodes.containsKey(errorCode);
|
||||
}
|
||||
|
||||
public static boolean isInvalidDataAccessApiUsageCode(Integer errorCode) {
|
||||
return errorCode == null ? false : invalidDataAccessApiUsageExeption.containsKey(errorCode);
|
||||
}
|
||||
|
||||
public static String getErrorDescription(Integer errorCode) {
|
||||
return errorCode == null ? null : errorCodes.get(errorCode);
|
||||
}
|
||||
}
|
||||
@@ -5,5 +5,4 @@ http\://www.springframework.org/schema/data/mongo/spring-mongo-1.3.xsd=org/sprin
|
||||
http\://www.springframework.org/schema/data/mongo/spring-mongo-1.4.xsd=org/springframework/data/mongodb/config/spring-mongo-1.4.xsd
|
||||
http\://www.springframework.org/schema/data/mongo/spring-mongo-1.5.xsd=org/springframework/data/mongodb/config/spring-mongo-1.5.xsd
|
||||
http\://www.springframework.org/schema/data/mongo/spring-mongo-1.7.xsd=org/springframework/data/mongodb/config/spring-mongo-1.7.xsd
|
||||
http\://www.springframework.org/schema/data/mongo/spring-mongo-1.8.xsd=org/springframework/data/mongodb/config/spring-mongo-1.8.xsd
|
||||
http\://www.springframework.org/schema/data/mongo/spring-mongo.xsd=org/springframework/data/mongodb/config/spring-mongo-1.8.xsd
|
||||
http\://www.springframework.org/schema/data/mongo/spring-mongo.xsd=org/springframework/data/mongodb/config/spring-mongo-1.7.xsd
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<xsd:element name="mongo" type="mongoType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="org.springframework.data.mongodb.core.MongoFactoryBean"><![CDATA[
|
||||
Deprecated since 1.7 - use mongo-client instead. Defines a Mongo instance used for accessing MongoDB.
|
||||
Defines a Mongo instance used for accessing MongoDB'.
|
||||
]]></xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation>
|
||||
@@ -31,7 +31,7 @@ Deprecated since 1.7 - use mongo-client instead. Defines a Mongo instance used f
|
||||
<xsd:element name="mongo-client" type="mongoClientType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="org.springframework.data.mongodb.core.MongoClientFactoryBean"><![CDATA[
|
||||
Defines a MongoClient instance used for accessing MongoDB.
|
||||
Defines a MongoClient instance used for accessing MongoDB'.
|
||||
]]></xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation>
|
||||
@@ -72,14 +72,14 @@ The name of the database to connect to. Default is 'db'.
|
||||
<xsd:attribute name="authentication-dbname" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Deprecated since 1.7 - Please use MongoClient internal authentication. The name of the authentication database to connect to. Default is 'db'.
|
||||
The name of the authentication database to connect to. Default is 'db'.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="port" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The port to connect to MongoDB server. Default is 27017
|
||||
The port to connect to MongoDB server. Default is 27017
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
@@ -93,14 +93,14 @@ The host to connect to a MongoDB server. Default is localhost
|
||||
<xsd:attribute name="username" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Deprecated since 1.7 - Please use MongoClient internal authentication. The username to use when connecting to a MongoDB server.
|
||||
The username to use when connecting to a MongoDB server.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="password" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Deprecated since 1.7 - Please use MongoClient internal authentication. The password to use when connecting to a MongoDB server.
|
||||
The password to use when connecting to a MongoDB server.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
@@ -382,11 +382,6 @@ The name of the Mongo object that determines what server to monitor. (by default
|
||||
</xsd:attributeGroup>
|
||||
-->
|
||||
<xsd:complexType name="mongoType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Deprecated since 1.7.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:sequence minOccurs="0" maxOccurs="1">
|
||||
<xsd:element name="options" type="optionsType">
|
||||
<xsd:annotation>
|
||||
@@ -444,11 +439,6 @@ The comma delimited list of host:port entries to use for replica set/pairs.
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="optionsType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Deprecated since 1.7.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:attribute name="connections-per-host" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
@@ -552,11 +542,6 @@ The SSLSocketFactory to use for the SSL connection. If none is configured here,
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="mongoClientType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Configuration options for 'MongoClient' - @since 1.7
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:sequence minOccurs="0" maxOccurs="1">
|
||||
<xsd:element name="client-options" type="clientOptionsType">
|
||||
<xsd:annotation>
|
||||
@@ -608,15 +593,10 @@ The comma delimited list of username:password@database entries to use for authen
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="clientOptionsType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Configuration options for 'MongoClientOptions' - @since 1.7
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:attribute name="description" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The MongoClient description.
|
||||
The MongoClient description.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
|
||||
@@ -1,894 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<xsd:schema xmlns="http://www.springframework.org/schema/data/mongo"
|
||||
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:tool="http://www.springframework.org/schema/tool"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:repository="http://www.springframework.org/schema/data/repository"
|
||||
targetNamespace="http://www.springframework.org/schema/data/mongo"
|
||||
elementFormDefault="qualified" attributeFormDefault="unqualified">
|
||||
|
||||
<xsd:import namespace="http://www.springframework.org/schema/beans" />
|
||||
<xsd:import namespace="http://www.springframework.org/schema/tool" />
|
||||
<xsd:import namespace="http://www.springframework.org/schema/context" />
|
||||
<xsd:import namespace="http://www.springframework.org/schema/data/repository"
|
||||
schemaLocation="http://www.springframework.org/schema/data/repository/spring-repository.xsd" />
|
||||
|
||||
<xsd:element name="mongo" type="mongoType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="org.springframework.data.mongodb.core.MongoFactoryBean"><![CDATA[
|
||||
Deprecated since 1.7 - use mongo-client instead. Defines a Mongo instance used for accessing MongoDB.
|
||||
]]></xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation>
|
||||
<tool:exports type="com.mongodb.Mongo"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="mongo-client" type="mongoClientType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="org.springframework.data.mongodb.core.MongoClientFactoryBean"><![CDATA[
|
||||
Defines a MongoClient instance used for accessing MongoDB.
|
||||
]]></xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation>
|
||||
<tool:exports type="com.mongodb.MongoClient"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="db-factory">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Defines a MongoDbFactory for connecting to a specific database
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="id" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The name of the mongo definition (by default "mongoDbFactory").]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="mongo-ref" type="mongoRef" use="optional">
|
||||
<xsd:annotation>
|
||||
<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>
|
||||
<xsd:attribute name="dbname" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The name of the database to connect to. Default is 'db'.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="authentication-dbname" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Deprecated since 1.7 - Please use MongoClient internal authentication. The name of the authentication database to connect to. Default is 'db'.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="port" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The port to connect to MongoDB server. Default is 27017
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="host" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The host to connect to a MongoDB server. Default is localhost
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="username" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Deprecated since 1.7 - Please use MongoClient internal authentication. The username to use when connecting to a MongoDB server.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="password" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Deprecated since 1.7 - Please use MongoClient internal authentication. The password to use when connecting to a MongoDB server.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="uri" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Deprecated since 1.8 - Please use client-uri instead. The Mongo URI string.]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="client-uri" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The MongoClientURI string.]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="write-concern">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
The WriteConcern that will be the default value used when asking the MongoDbFactory for a DB object
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
<xsd:union memberTypes="writeConcernEnumeration xsd:string"/>
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:attributeGroup name="mongo-repository-attributes">
|
||||
<xsd:attribute name="mongo-template-ref" type="mongoTemplateRef" default="mongoTemplate">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
The reference to a MongoTemplate. Will default to 'mongoTemplate'.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="create-query-indexes" type="xsd:boolean" default="false">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Enables creation of indexes for queries that get derived from the method name
|
||||
and thus reference domain class properties. Defaults to false.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:attributeGroup>
|
||||
|
||||
<xsd:element name="repositories">
|
||||
<xsd:complexType>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="repository:repositories">
|
||||
<xsd:attributeGroup ref="mongo-repository-attributes"/>
|
||||
<xsd:attributeGroup ref="repository:repository-attributes"/>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="mapping-converter">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[Defines a MongoConverter for getting rich mapping functionality.]]></xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:exports type="org.springframework.data.mongodb.core.convert.MappingMongoConverter" />
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="custom-converters" minOccurs="0">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Top-level element that contains one or more custom converters to be used for mapping
|
||||
domain objects to and from Mongo's DBObject]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="converter" type="customConverterType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="base-package" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="id" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The name of the MappingMongoConverter instance (by default "mappingConverter").]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="base-package" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The base package in which to scan for entities annotated with @Document
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="db-factory-ref" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
The reference to a DbFactory.
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:assignable-to type="org.springframework.data.mongodb.MongoDbFactory" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="type-mapper-ref" type="typeMapperRef" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
The reference to a MongoTypeMapper to be used by this MappingMongoConverter.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="mapping-context-ref" type="mappingContextRef" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="org.springframework.data.mapping.model.MappingContext">
|
||||
The reference to a MappingContext. Will default to 'mappingContext'.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="disable-validation" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="org.springframework.data.mongodb.core.mapping.event.ValidatingMongoEventListener">
|
||||
Disables JSR-303 validation on MongoDB documents before they are saved. By default it is set to false.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
<xsd:union memberTypes="xsd:boolean xsd:string"/>
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="abbreviate-field-names" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="org.springframework.data.mongodb.core.mapping.CamelCaseAbbreviatingFieldNamingStrategy">
|
||||
Enables abbreviating the field names for domain class properties to the
|
||||
first character of their camel case names, e.g. fooBar -> fb. Defaults to false.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
<xsd:union memberTypes="xsd:boolean xsd:string"/>
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="field-naming-strategy-ref" type="fieldNamingStrategyRef" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="org.springframework.data.mongodb.core.mapping.FieldNamingStrategy">
|
||||
The reference to a FieldNamingStrategy.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="jmx">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Defines a JMX Model MBeans for monitoring a MongoDB server'.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="mongo-ref" type="mongoRef" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The name of the Mongo object that determines what server to monitor. (by default "mongo").]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="auditing">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation>
|
||||
<tool:exports type="org.springframework.data.mongodb.core.mapping.event.AuditingEventListener" />
|
||||
<tool:exports type="org.springframework.data.auditing.IsNewAwareAuditingHandler" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:attributeGroup ref="repository:auditing-attributes" />
|
||||
<xsd:attribute name="mapping-context-ref" type="mappingContextRef" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:simpleType name="typeMapperRef">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:assignable-to type="org.springframework.data.mongodb.core.convert.MongoTypeMapper"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
<xsd:union memberTypes="xsd:string"/>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="mappingContextRef">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:assignable-to type="org.springframework.data.mapping.model.MappingContext"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
<xsd:union memberTypes="xsd:string"/>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="fieldNamingStrategyRef">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:assignable-to type="org.springframework.data.mongodb.core.mapping.FieldNamingStrategy"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
<xsd:union memberTypes="xsd:string"/>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="mongoTemplateRef">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:assignable-to type="org.springframework.data.mongodb.core.MongoTemplate"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
<xsd:union memberTypes="xsd:string"/>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="mongoRef">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:assignable-to type="org.springframework.data.mongodb.core.MongoFactoryBean"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
<xsd:union memberTypes="xsd:string"/>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="sslSocketFactoryRef">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:assignable-to type="javax.net.ssl.SSLSocketFactory"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
<xsd:union memberTypes="xsd:string"/>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="writeConcernEnumeration">
|
||||
<xsd:restriction base="xsd:token">
|
||||
<xsd:enumeration value="NONE" />
|
||||
<xsd:enumeration value="NORMAL" />
|
||||
<xsd:enumeration value="SAFE" />
|
||||
<xsd:enumeration value="FSYNC_SAFE" />
|
||||
<xsd:enumeration value="REPLICAS_SAFE" />
|
||||
<xsd:enumeration value="JOURNAL_SAFE" />
|
||||
<xsd:enumeration value="MAJORITY" />
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="readPreferenceEnumeration">
|
||||
<xsd:restriction base="xsd:token">
|
||||
<xsd:enumeration value="PRIMARY" />
|
||||
<xsd:enumeration value="PRIMARY_PREFERRED" />
|
||||
<xsd:enumeration value="SECONDARY" />
|
||||
<xsd:enumeration value="SECONDARY_PREFERRED" />
|
||||
<xsd:enumeration value="NEAREST" />
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
<!-- MLP
|
||||
<xsd:attributeGroup name="writeConcern">
|
||||
<xsd:attribute name="write-concern">
|
||||
<xsd:simpleType>
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:enumeration value="NONE" />
|
||||
<xsd:enumeration value="NORMAL" />
|
||||
<xsd:enumeration value="SAFE" />
|
||||
<xsd:enumeration value="FSYNC_SAFE" />
|
||||
<xsd:enumeration value="REPLICA_SAFE" />
|
||||
<xsd:enumeration value="JOURNAL_SAFE" />
|
||||
<xsd:enumeration value="MAJORITY" />
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
</xsd:attributeGroup>
|
||||
-->
|
||||
<xsd:complexType name="mongoType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Deprecated since 1.7.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:sequence minOccurs="0" maxOccurs="1">
|
||||
<xsd:element name="options" type="optionsType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The Mongo driver options
|
||||
]]></xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation>
|
||||
<tool:exports type="com.mongodb.MongoOptions"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="write-concern">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
The WriteConcern that will be the default value used when asking the MongoDbFactory for a DB object
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
<xsd:union memberTypes="writeConcernEnumeration xsd:string"/>
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
<!-- MLP
|
||||
<xsd:attributeGroup ref="writeConcern" />
|
||||
-->
|
||||
<xsd:attribute name="id" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The name of the mongo definition (by default "mongo").]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="port" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The port to connect to MongoDB server. Default is 27017
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="host" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The host to connect to a MongoDB server. Default is localhost
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="replica-set" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The comma delimited list of host:port entries to use for replica set/pairs.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="optionsType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Deprecated since 1.7.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:attribute name="connections-per-host" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The number of connections allowed per host. Will block if run out. Default is 10. System property MONGO.POOLSIZE can override
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="threads-allowed-to-block-for-connection-multiplier" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The multiplier for connectionsPerHost for # of threads that can block. Default is 5.
|
||||
If connectionsPerHost is 10, and threadsAllowedToBlockForConnectionMultiplier is 5,
|
||||
then 50 threads can block more than that and an exception will be thrown.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="max-wait-time" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The max wait time of a blocking thread for a connection. Default is 12000 ms (2 minutes)
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="connect-timeout" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The connect timeout in milliseconds. 0 is default and infinite.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="socket-timeout" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The socket timeout. 0 is default and infinite.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="socket-keep-alive" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The keep alive flag, controls whether or not to have socket keep alive timeout. Defaults to false.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="auto-connect-retry" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
This controls whether or not on a connect, the system retries automatically. Default is false.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="max-auto-connect-retry-time" type="xsd:long">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The maximum amount of time in millisecons to spend retrying to open connection to the same server. Default is 0, which means to use the default 15s if autoConnectRetry is on.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="write-number" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
This specifies the number of servers to wait for on the write operation, and exception raising behavior. The 'w' option to the getlasterror command. Defaults to 0.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="write-timeout" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
This controls timeout for write operations in milliseconds. The 'wtimeout' option to the getlasterror command. Defaults to 0 (indefinite). Greater than zero is number of milliseconds to wait.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="write-fsync" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
This controls whether or not to fsync. The 'fsync' option to the getlasterror command. Defaults to false.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="slave-ok" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
This controls if the driver is allowed to read from secondaries or slaves. Defaults to false.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="ssl" type="xsd:boolean">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
This controls if the driver should us an SSL connection. Defaults to false.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="ssl-socket-factory-ref" type="sslSocketFactoryRef" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The SSLSocketFactory to use for the SSL connection. If none is configured here, SSLSocketFactory#getDefault() will be used.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="mongoClientType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Configuration options for 'MongoClient' - @since 1.7
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:sequence minOccurs="0" maxOccurs="1">
|
||||
<xsd:element name="client-options" type="clientOptionsType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The Mongo driver options
|
||||
]]></xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation>
|
||||
<tool:exports type="com.mongodb.MongoClientOptions"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="id" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The name of the mongo definition (by default "mongoClient").]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="port" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The port to connect to MongoDB server. Default is 27017
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="host" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The host to connect to a MongoDB server. Default is localhost
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="replica-set" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The comma delimited list of host:port entries to use for replica set/pairs.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="credentials" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The comma delimited list of username:password@database entries to use for authentication. Appending ?uri.authMechanism allows to specify the authentication challenge mechanism. If the credential you're trying to pass contains a comma itself, quote it with single quotes: '…'.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="clientOptionsType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Configuration options for 'MongoClientOptions' - @since 1.7
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:attribute name="description" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The MongoClient description.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="min-connections-per-host" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The minimum number of connections per host.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="connections-per-host" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The number of connections allowed per host. Will block if run out. Default is 10. System property MONGO.POOLSIZE can override
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="threads-allowed-to-block-for-connection-multiplier" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The multiplier for connectionsPerHost for # of threads that can block. Default is 5.
|
||||
If connectionsPerHost is 10, and threadsAllowedToBlockForConnectionMultiplier is 5,
|
||||
then 50 threads can block more than that and an exception will be thrown.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="max-wait-time" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The max wait time of a blocking thread for a connection. Default is 12000 ms (2 minutes)
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="max-connection-idle-time" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The maximum idle time for a pooled connection.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="max-connection-life-time" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The maximum life time for a pooled connection.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="connect-timeout" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The connect timeout in milliseconds. 0 is default and infinite.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="socket-timeout" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The socket timeout. 0 is default and infinite.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="socket-keep-alive" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The keep alive flag, controls whether or not to have socket keep alive timeout. Defaults to false.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="read-preference">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The read preference.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
<xsd:union memberTypes="readPreferenceEnumeration xsd:string"/>
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="write-concern">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The WriteConcern that will be the default value used when asking the MongoDbFactory for a DB object
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
<xsd:union memberTypes="writeConcernEnumeration xsd:string"/>
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="heartbeat-frequency" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
This is the frequency that the driver will attempt to determine the current state of each server in the cluster.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="min-heartbeat-frequency" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
In the event that the driver has to frequently re-check a server's availability, it will wait at least this long since the previous check to avoid wasted effort.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="heartbeat-connect-timeout" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The connect timeout for connections used for the cluster heartbeat.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="heartbeat-socket-timeout" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The socket timeout for connections used for the cluster heartbeat.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="ssl" type="xsd:boolean">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
This controls if the driver should us an SSL connection. Defaults to false.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="ssl-socket-factory-ref" type="sslSocketFactoryRef" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The SSLSocketFactory to use for the SSL connection. If none is configured here, SSLSocketFactory#getDefault() will be used.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:group name="beanElementGroup">
|
||||
<xsd:choice>
|
||||
<xsd:element ref="beans:bean"/>
|
||||
<xsd:element ref="beans:ref"/>
|
||||
</xsd:choice>
|
||||
</xsd:group>
|
||||
|
||||
<xsd:complexType name="customConverterType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Element defining a custom converterr.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:group ref="beanElementGroup" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:attribute name="ref" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
A reference to a custom converter.
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref"/>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:simpleType name="converterRef">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:assignable-to type="org.springframework.data.mongodb.core.convert.MongoConverter"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
<xsd:union memberTypes="xsd:string"/>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:element name="template">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Defines a MongoDbFactory for connecting to a specific database
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="id" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The name of the mongo definition (by default "mongoDbFactory").]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="converter-ref" type="converterRef" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The reference to a Mongoconverter instance.
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:assignable-to type="org.springframework.data.mongodb.core.convert.MongoConverter"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="db-factory-ref" type="xsd:string"
|
||||
use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
The reference to a DbFactory.
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:assignable-to
|
||||
type="org.springframework.data.mongodb.MongoDbFactory" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="write-concern">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
The WriteConcern that will be the default value used when asking the MongoDbFactory for a DB object
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
<xsd:union memberTypes="writeConcernEnumeration xsd:string"/>
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="gridFsTemplate">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Defines a MongoDbFactory for connecting to a specific database
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="id" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The name of the mongo definition (by default "mongoDbFactory").]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="converter-ref" type="converterRef" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The reference to a Mongoconverter instance.
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:assignable-to type="org.springframework.data.mongodb.core.convert.MongoConverter"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="db-factory-ref" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
The reference to a DbFactory.
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:assignable-to type="org.springframework.data.mongodb.MongoDbFactory" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="bucket" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The GridFs bucket string.]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
@@ -47,7 +47,7 @@ public class AuditingIntegrationTests {
|
||||
mappingContext.getPersistentEntity(Entity.class);
|
||||
|
||||
Entity entity = new Entity();
|
||||
BeforeConvertEvent<Entity> event = new BeforeConvertEvent<Entity>(entity, "collection-1");
|
||||
BeforeConvertEvent<Entity> event = new BeforeConvertEvent<Entity>(entity);
|
||||
context.publishEvent(event);
|
||||
|
||||
assertThat(entity.created, is(notNullValue()));
|
||||
@@ -55,7 +55,7 @@ public class AuditingIntegrationTests {
|
||||
|
||||
Thread.sleep(10);
|
||||
entity.id = 1L;
|
||||
event = new BeforeConvertEvent<Entity>(entity, "collection-1");
|
||||
event = new BeforeConvertEvent<Entity>(entity);
|
||||
context.publishEvent(event);
|
||||
|
||||
assertThat(entity.created, is(notNullValue()));
|
||||
|
||||
@@ -41,7 +41,6 @@ import org.springframework.test.util.ReflectionTestUtils;
|
||||
import com.mongodb.DB;
|
||||
import com.mongodb.Mongo;
|
||||
import com.mongodb.MongoClient;
|
||||
import com.mongodb.MongoClientURI;
|
||||
import com.mongodb.MongoURI;
|
||||
import com.mongodb.WriteConcern;
|
||||
|
||||
@@ -50,7 +49,6 @@ import com.mongodb.WriteConcern;
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
* @author Viktor Khoroshko
|
||||
*/
|
||||
public class MongoDbFactoryParserIntegrationTests {
|
||||
|
||||
@@ -176,75 +174,6 @@ public class MongoDbFactoryParserIntegrationTests {
|
||||
reader.loadBeanDefinitions(new ClassPathResource("namespace/mongo-uri-and-details.xml"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1218
|
||||
*/
|
||||
@Test
|
||||
public void setsUpMongoDbFactoryUsingAMongoClientUri() {
|
||||
|
||||
reader.loadBeanDefinitions(new ClassPathResource("namespace/mongo-client-uri.xml"));
|
||||
BeanDefinition definition = factory.getBeanDefinition("mongoDbFactory");
|
||||
ConstructorArgumentValues constructorArguments = definition.getConstructorArgumentValues();
|
||||
|
||||
assertThat(constructorArguments.getArgumentCount(), is(1));
|
||||
ValueHolder argument = constructorArguments.getArgumentValue(0, MongoClientURI.class);
|
||||
assertThat(argument, is(notNullValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1218
|
||||
*/
|
||||
@Test(expected = BeanDefinitionParsingException.class)
|
||||
public void rejectsClientUriPlusDetailedConfiguration() {
|
||||
reader.loadBeanDefinitions(new ClassPathResource("namespace/mongo-client-uri-and-details.xml"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1293
|
||||
*/
|
||||
@Test
|
||||
public void setsUpClientUriWithId() {
|
||||
|
||||
reader.loadBeanDefinitions(new ClassPathResource("namespace/mongo-client-uri-and-id.xml"));
|
||||
BeanDefinition definition = factory.getBeanDefinition("testMongo");
|
||||
ConstructorArgumentValues constructorArguments = definition.getConstructorArgumentValues();
|
||||
|
||||
assertThat(constructorArguments.getArgumentCount(), is(1));
|
||||
ValueHolder argument = constructorArguments.getArgumentValue(0, MongoClientURI.class);
|
||||
assertThat(argument, is(notNullValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1293
|
||||
*/
|
||||
@Test
|
||||
public void setsUpUriWithId() {
|
||||
|
||||
reader.loadBeanDefinitions(new ClassPathResource("namespace/mongo-uri-and-id.xml"));
|
||||
BeanDefinition definition = factory.getBeanDefinition("testMongo");
|
||||
ConstructorArgumentValues constructorArguments = definition.getConstructorArgumentValues();
|
||||
|
||||
assertThat(constructorArguments.getArgumentCount(), is(1));
|
||||
ValueHolder argument = constructorArguments.getArgumentValue(0, MongoClientURI.class);
|
||||
assertThat(argument, is(notNullValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1293
|
||||
*/
|
||||
@Test(expected = BeanDefinitionParsingException.class)
|
||||
public void rejectsClientUriPlusDetailedConfigurationAndWriteConcern() {
|
||||
reader.loadBeanDefinitions(new ClassPathResource("namespace/mongo-client-uri-write-concern-and-details.xml"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1293
|
||||
*/
|
||||
@Test(expected = BeanDefinitionParsingException.class)
|
||||
public void rejectsUriPlusDetailedConfigurationAndWriteConcern() {
|
||||
reader.loadBeanDefinitions(new ClassPathResource("namespace/mongo-client-uri-write-concern-and-details.xml"));
|
||||
}
|
||||
|
||||
private static void assertWriteConcern(ClassPathXmlApplicationContext ctx, WriteConcern expectedWriteConcern) {
|
||||
|
||||
SimpleMongoDbFactory dbFactory = ctx.getBean("first", SimpleMongoDbFactory.class);
|
||||
|
||||
@@ -1,343 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 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.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.mongodb.BulkOperationException;
|
||||
import org.springframework.data.mongodb.core.BulkOperations.BulkMode;
|
||||
import org.springframework.data.mongodb.core.query.Criteria;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.data.mongodb.core.query.Update;
|
||||
import org.springframework.data.util.Tuple;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.BulkWriteResult;
|
||||
import com.mongodb.DBCollection;
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.WriteConcern;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link DefaultBulkOperations}.
|
||||
*
|
||||
* @author Tobias Trelle
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration("classpath:infrastructure.xml")
|
||||
public class DefaultBulkOperationsIntegrationTests {
|
||||
|
||||
static final String COLLECTION_NAME = "bulk_ops";
|
||||
|
||||
@Autowired MongoOperations operations;
|
||||
|
||||
DBCollection collection;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
this.collection = this.operations.getCollection(COLLECTION_NAME);
|
||||
this.collection.remove(new BasicDBObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-934
|
||||
*/
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsNullMongoOperations() {
|
||||
new DefaultBulkOperations(null, null, COLLECTION_NAME, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-934
|
||||
*/
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsNullCollectionName() {
|
||||
new DefaultBulkOperations(operations, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-934
|
||||
*/
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsEmptyCollectionName() {
|
||||
new DefaultBulkOperations(operations, null, "", null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-934
|
||||
*/
|
||||
@Test
|
||||
public void insertOrdered() {
|
||||
|
||||
List<BaseDoc> documents = Arrays.asList(newDoc("1"), newDoc("2"));
|
||||
|
||||
assertThat(createBulkOps(BulkMode.ORDERED).insert(documents).execute().getInsertedCount(), is(2));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-934
|
||||
*/
|
||||
@Test
|
||||
public void insertOrderedFails() {
|
||||
|
||||
List<BaseDoc> documents = Arrays.asList(newDoc("1"), newDoc("1"), newDoc("2"));
|
||||
|
||||
try {
|
||||
createBulkOps(BulkMode.ORDERED).insert(documents).execute();
|
||||
fail();
|
||||
} catch (BulkOperationException e) {
|
||||
assertThat(e.getResult().getInsertedCount(), is(1)); // fails after first error
|
||||
assertThat(e.getErrors(), notNullValue());
|
||||
assertThat(e.getErrors().size(), is(1));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-934
|
||||
*/
|
||||
@Test
|
||||
public void insertUnOrdered() {
|
||||
|
||||
List<BaseDoc> documents = Arrays.asList(newDoc("1"), newDoc("2"));
|
||||
|
||||
assertThat(createBulkOps(BulkMode.UNORDERED).insert(documents).execute().getInsertedCount(), is(2));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-934
|
||||
*/
|
||||
@Test
|
||||
public void insertUnOrderedContinuesOnError() {
|
||||
|
||||
List<BaseDoc> documents = Arrays.asList(newDoc("1"), newDoc("1"), newDoc("2"));
|
||||
|
||||
try {
|
||||
createBulkOps(BulkMode.UNORDERED).insert(documents).execute();
|
||||
fail();
|
||||
} catch (BulkOperationException e) {
|
||||
assertThat(e.getResult().getInsertedCount(), is(2)); // two docs were inserted
|
||||
assertThat(e.getErrors(), notNullValue());
|
||||
assertThat(e.getErrors().size(), is(1));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-934
|
||||
*/
|
||||
@Test
|
||||
public void upsertDoesUpdate() {
|
||||
|
||||
insertSomeDocuments();
|
||||
|
||||
BulkWriteResult result = createBulkOps(BulkMode.ORDERED).//
|
||||
upsert(where("value", "value1"), set("value", "value2")).//
|
||||
execute();
|
||||
|
||||
assertThat(result, notNullValue());
|
||||
assertThat(result.getMatchedCount(), is(2));
|
||||
assertThat(result.getModifiedCount(), is(2));
|
||||
assertThat(result.getInsertedCount(), is(0));
|
||||
assertThat(result.getUpserts(), is(notNullValue()));
|
||||
assertThat(result.getUpserts().size(), is(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-934
|
||||
*/
|
||||
@Test
|
||||
public void upsertDoesInsert() {
|
||||
|
||||
BulkWriteResult result = createBulkOps(BulkMode.ORDERED).//
|
||||
upsert(where("_id", "1"), set("value", "v1")).//
|
||||
execute();
|
||||
|
||||
assertThat(result, notNullValue());
|
||||
assertThat(result.getMatchedCount(), is(0));
|
||||
assertThat(result.getModifiedCount(), is(0));
|
||||
assertThat(result.getUpserts(), is(notNullValue()));
|
||||
assertThat(result.getUpserts().size(), is(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-934
|
||||
*/
|
||||
@Test
|
||||
public void updateOneOrdered() {
|
||||
testUpdate(BulkMode.ORDERED, false, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-934
|
||||
*/
|
||||
@Test
|
||||
public void updateMultiOrdered() {
|
||||
testUpdate(BulkMode.ORDERED, true, 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-934
|
||||
*/
|
||||
@Test
|
||||
public void updateOneUnOrdered() {
|
||||
testUpdate(BulkMode.UNORDERED, false, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-934
|
||||
*/
|
||||
@Test
|
||||
public void updateMultiUnOrdered() {
|
||||
testUpdate(BulkMode.UNORDERED, true, 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-934
|
||||
*/
|
||||
@Test
|
||||
public void removeOrdered() {
|
||||
testRemove(BulkMode.ORDERED);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-934
|
||||
*/
|
||||
@Test
|
||||
public void removeUnordered() {
|
||||
testRemove(BulkMode.UNORDERED);
|
||||
}
|
||||
|
||||
/**
|
||||
* If working on the same set of documents, only an ordered bulk operation will yield predictable results.
|
||||
*
|
||||
* @see DATAMONGO-934
|
||||
*/
|
||||
@Test
|
||||
public void mixedBulkOrdered() {
|
||||
|
||||
BulkWriteResult result = createBulkOps(BulkMode.ORDERED).insert(newDoc("1", "v1")).//
|
||||
updateOne(where("_id", "1"), set("value", "v2")).//
|
||||
remove(where("value", "v2")).//
|
||||
execute();
|
||||
|
||||
assertThat(result, notNullValue());
|
||||
assertThat(result.getInsertedCount(), is(1));
|
||||
assertThat(result.getModifiedCount(), is(1));
|
||||
assertThat(result.getRemovedCount(), is(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* If working on the same set of documents, only an ordered bulk operation will yield predictable results.
|
||||
*/
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void mixedBulkOrderedWithList() {
|
||||
|
||||
List<BaseDoc> inserts = Arrays.asList(newDoc("1", "v1"), newDoc("2", "v2"), newDoc("3", "v2"));
|
||||
List<Tuple<Query, Update>> updates = Arrays.asList(Tuple.of(where("value", "v2"), set("value", "v3")));
|
||||
List<Query> removes = Arrays.asList(where("_id", "1"));
|
||||
|
||||
BulkWriteResult result = createBulkOps(BulkMode.ORDERED).insert(inserts).updateMulti(updates).remove(removes)
|
||||
.execute();
|
||||
|
||||
assertThat(result, notNullValue());
|
||||
assertThat(result.getInsertedCount(), is(3));
|
||||
assertThat(result.getModifiedCount(), is(2));
|
||||
assertThat(result.getRemovedCount(), is(1));
|
||||
}
|
||||
|
||||
private void testUpdate(BulkMode mode, boolean multi, int expectedUpdates) {
|
||||
|
||||
BulkOperations bulkOps = createBulkOps(mode);
|
||||
|
||||
insertSomeDocuments();
|
||||
|
||||
List<Tuple<Query, Update>> updates = new ArrayList<Tuple<Query, Update>>();
|
||||
updates.add(Tuple.of(where("value", "value1"), set("value", "value3")));
|
||||
updates.add(Tuple.of(where("value", "value2"), set("value", "value4")));
|
||||
|
||||
int modifiedCount = multi ? bulkOps.updateMulti(updates).execute().getModifiedCount()
|
||||
: bulkOps.updateOne(updates).execute().getModifiedCount();
|
||||
|
||||
assertThat(modifiedCount, is(expectedUpdates));
|
||||
}
|
||||
|
||||
private void testRemove(BulkMode mode) {
|
||||
|
||||
insertSomeDocuments();
|
||||
|
||||
List<Query> removes = Arrays.asList(where("_id", "1"), where("value", "value2"));
|
||||
|
||||
assertThat(createBulkOps(mode).remove(removes).execute().getRemovedCount(), is(3));
|
||||
}
|
||||
|
||||
private BulkOperations createBulkOps(BulkMode mode) {
|
||||
|
||||
DefaultBulkOperations operations = new DefaultBulkOperations(this.operations, mode, COLLECTION_NAME, null);
|
||||
operations.setDefaultWriteConcern(WriteConcern.ACKNOWLEDGED);
|
||||
|
||||
return operations;
|
||||
}
|
||||
|
||||
private void insertSomeDocuments() {
|
||||
|
||||
final DBCollection coll = operations.getCollection(COLLECTION_NAME);
|
||||
|
||||
coll.insert(rawDoc("1", "value1"));
|
||||
coll.insert(rawDoc("2", "value1"));
|
||||
coll.insert(rawDoc("3", "value2"));
|
||||
coll.insert(rawDoc("4", "value2"));
|
||||
}
|
||||
|
||||
private static BaseDoc newDoc(String id) {
|
||||
|
||||
BaseDoc doc = new BaseDoc();
|
||||
doc.id = id;
|
||||
|
||||
return doc;
|
||||
}
|
||||
|
||||
private static BaseDoc newDoc(String id, String value) {
|
||||
|
||||
BaseDoc doc = newDoc(id);
|
||||
doc.value = value;
|
||||
|
||||
return doc;
|
||||
}
|
||||
|
||||
private static Query where(String field, String value) {
|
||||
return new Query().addCriteria(Criteria.where(field).is(value));
|
||||
}
|
||||
|
||||
private static Update set(String field, String value) {
|
||||
return new Update().set(field, value);
|
||||
}
|
||||
|
||||
private static DBObject rawDoc(String id, String value) {
|
||||
return new BasicDBObject("_id", id).append("value", value);
|
||||
}
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 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.core.Is.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.data.mongodb.core.query.Criteria.*;
|
||||
import static org.springframework.data.mongodb.core.query.Query.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.mongodb.config.AbstractMongoConfiguration;
|
||||
import org.springframework.data.mongodb.repository.MongoRepository;
|
||||
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import com.mongodb.Mongo;
|
||||
import com.mongodb.MongoClient;
|
||||
|
||||
/**
|
||||
* Integration tests for DATAMONGO-1289.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
public class NoExplicitIdTests {
|
||||
|
||||
@Configuration
|
||||
@EnableMongoRepositories(considerNestedRepositories = true)
|
||||
static class Config extends AbstractMongoConfiguration {
|
||||
|
||||
@Override
|
||||
protected String getDatabaseName() {
|
||||
return "test";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mongo mongo() throws Exception {
|
||||
return new MongoClient();
|
||||
}
|
||||
}
|
||||
|
||||
@Autowired MongoOperations mongoOps;
|
||||
@Autowired TypeWithoutExplicitIdPropertyRepository repo;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mongoOps.dropCollection(TypeWithoutIdProperty.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1289
|
||||
*/
|
||||
@Test
|
||||
public void saveAndRetrieveTypeWithoutIdPorpertyViaTemplate() {
|
||||
|
||||
TypeWithoutIdProperty noid = new TypeWithoutIdProperty();
|
||||
noid.someString = "o.O";
|
||||
|
||||
mongoOps.save(noid);
|
||||
|
||||
TypeWithoutIdProperty retrieved = mongoOps.findOne(query(where("someString").is(noid.someString)),
|
||||
TypeWithoutIdProperty.class);
|
||||
|
||||
assertThat(retrieved.someString, is(noid.someString));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1289
|
||||
*/
|
||||
@Test
|
||||
public void saveAndRetrieveTypeWithoutIdPorpertyViaRepository() {
|
||||
|
||||
TypeWithoutIdProperty noid = new TypeWithoutIdProperty();
|
||||
noid.someString = "o.O";
|
||||
|
||||
repo.save(noid);
|
||||
|
||||
TypeWithoutIdProperty retrieved = repo.findBySomeString(noid.someString);
|
||||
assertThat(retrieved.someString, is(noid.someString));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1289
|
||||
*/
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void saveAndRetrieveTypeWithoutIdPorpertyViaRepositoryFindOne() {
|
||||
|
||||
TypeWithoutIdProperty noid = new TypeWithoutIdProperty();
|
||||
noid.someString = "o.O";
|
||||
|
||||
repo.save(noid);
|
||||
|
||||
Map<String, Object> map = mongoOps.findOne(query(where("someString").is(noid.someString)), Map.class,
|
||||
"typeWithoutIdProperty");
|
||||
|
||||
TypeWithoutIdProperty retrieved = repo.findOne(map.get("_id").toString());
|
||||
assertThat(retrieved.someString, is(noid.someString));
|
||||
}
|
||||
|
||||
static class TypeWithoutIdProperty {
|
||||
|
||||
String someString;
|
||||
}
|
||||
|
||||
static interface TypeWithoutExplicitIdPropertyRepository extends MongoRepository<TypeWithoutIdProperty, String> {
|
||||
|
||||
TypeWithoutIdProperty findBySomeString(String someString);
|
||||
}
|
||||
}
|
||||
@@ -50,7 +50,7 @@ public class UnwrapAndReadDbObjectCallbackUnitTests {
|
||||
MappingMongoConverter converter = new MappingMongoConverter(new DefaultDbRefResolver(factory),
|
||||
new MongoMappingContext());
|
||||
|
||||
this.callback = template.new UnwrapAndReadDbObjectCallback<Target>(converter, Target.class, "collection-1");
|
||||
this.callback = template.new UnwrapAndReadDbObjectCallback<Target>(converter, Target.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2016 the original author or authors.
|
||||
* Copyright 2011-2015 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.
|
||||
@@ -24,7 +24,6 @@ import java.text.Format;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Currency;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.UUID;
|
||||
@@ -272,18 +271,6 @@ public class CustomConversionsUnitTests {
|
||||
assertThat(customConversions.getCustomWriteTarget(String.class, SimpleDateFormat.class), notNullValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1372
|
||||
*/
|
||||
@Test
|
||||
public void registersConvertersForCurrency() {
|
||||
|
||||
CustomConversions customConversions = new CustomConversions();
|
||||
|
||||
assertThat(customConversions.hasCustomWriteTarget(Currency.class), is(true));
|
||||
assertThat(customConversions.hasCustomReadTarget(String.class, Currency.class), is(true));
|
||||
}
|
||||
|
||||
private static Class<?> createProxyTypeFor(Class<?> type) {
|
||||
|
||||
ProxyFactory factory = new ProxyFactory();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2016 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.
|
||||
@@ -48,9 +48,9 @@ public class DefaultMongoTypeMapperUnitTests {
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
configurableTypeInformationMapper = new ConfigurableTypeInformationMapper(
|
||||
Collections.singletonMap(String.class, "1"));
|
||||
simpleTypeInformationMapper = new SimpleTypeInformationMapper();
|
||||
configurableTypeInformationMapper = new ConfigurableTypeInformationMapper(Collections.singletonMap(String.class,
|
||||
"1"));
|
||||
simpleTypeInformationMapper = SimpleTypeInformationMapper.INSTANCE;
|
||||
|
||||
typeMapper = new DefaultMongoTypeMapper();
|
||||
}
|
||||
@@ -81,8 +81,8 @@ public class DefaultMongoTypeMapperUnitTests {
|
||||
@Test
|
||||
public void writesClassNamesForUnmappedValuesIfConfigured() {
|
||||
|
||||
typeMapper = new DefaultMongoTypeMapper(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY,
|
||||
Arrays.asList(configurableTypeInformationMapper, simpleTypeInformationMapper));
|
||||
typeMapper = new DefaultMongoTypeMapper(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY, Arrays.asList(
|
||||
configurableTypeInformationMapper, simpleTypeInformationMapper));
|
||||
|
||||
writesTypeToField(new BasicDBObject(), String.class, "1");
|
||||
writesTypeToField(new BasicDBObject(), Object.class, Object.class.getName());
|
||||
@@ -101,12 +101,11 @@ public class DefaultMongoTypeMapperUnitTests {
|
||||
@Test
|
||||
public void readsTypeLoadingClassesForUnmappedTypesIfConfigured() {
|
||||
|
||||
typeMapper = new DefaultMongoTypeMapper(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY,
|
||||
Arrays.asList(configurableTypeInformationMapper, simpleTypeInformationMapper));
|
||||
typeMapper = new DefaultMongoTypeMapper(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY, Arrays.asList(
|
||||
configurableTypeInformationMapper, simpleTypeInformationMapper));
|
||||
|
||||
readsTypeFromField(new BasicDBObject(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY, "1"), String.class);
|
||||
readsTypeFromField(new BasicDBObject(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY, Object.class.getName()),
|
||||
Object.class);
|
||||
readsTypeFromField(new BasicDBObject(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY, Object.class.getName()), Object.class);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -145,8 +144,7 @@ public class DefaultMongoTypeMapperUnitTests {
|
||||
|
||||
@Test
|
||||
public void readsTypeFromDefaultKeyByDefault() {
|
||||
readsTypeFromField(new BasicDBObject(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY, String.class.getName()),
|
||||
String.class);
|
||||
readsTypeFromField(new BasicDBObject(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY, String.class.getName()), String.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2016 by the original author(s).
|
||||
* Copyright (c) 2011-2014 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.
|
||||
@@ -19,7 +19,6 @@ import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Currency;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.geo.Box;
|
||||
@@ -28,9 +27,7 @@ import org.springframework.data.geo.Point;
|
||||
import org.springframework.data.geo.Polygon;
|
||||
import org.springframework.data.geo.Shape;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.BigDecimalToStringConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.CurrencyToStringConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.StringToBigDecimalConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.StringToCurrencyConverter;
|
||||
import org.springframework.data.mongodb.core.geo.Sphere;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
@@ -40,7 +37,6 @@ import com.mongodb.DBObject;
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Darimont
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class MongoConvertersUnitTests {
|
||||
|
||||
@@ -124,20 +120,4 @@ public class MongoConvertersUnitTests {
|
||||
|
||||
assertThat(converted, is((org.springframework.data.geo.Point) point));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1372
|
||||
*/
|
||||
@Test
|
||||
public void convertsCurrencyToStringCorrectly() {
|
||||
assertThat(CurrencyToStringConverter.INSTANCE.convert(Currency.getInstance("USD")), is("USD"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1372
|
||||
*/
|
||||
@Test
|
||||
public void convertsStringToCurrencyCorrectly() {
|
||||
assertThat(StringToCurrencyConverter.INSTANCE.convert("USD"), is(Currency.getInstance("USD")));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015-2016 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.convert;
|
||||
|
||||
import static org.hamcrest.core.Is.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameter;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.NumberToNumberConverterFactory;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
@RunWith(Parameterized.class)
|
||||
public class NumberToNumberConverterFactoryUnitTests {
|
||||
|
||||
public @Parameter(0) Number source;
|
||||
|
||||
public @Parameter(1) Number expected;
|
||||
|
||||
@Parameters
|
||||
public static Collection<Number[]> parameters() {
|
||||
|
||||
Number[] longToInt = new Number[] { new Long(10), new Integer(10) };
|
||||
Number[] atomicIntToInt = new Number[] { new AtomicInteger(10), new Integer(10) };
|
||||
Number[] atomicIntToDouble = new Number[] { new AtomicInteger(10), new Double(10) };
|
||||
Number[] atomicLongToInt = new Number[] { new AtomicLong(10), new Integer(10) };
|
||||
Number[] atomicLongToLong = new Number[] { new AtomicLong(10), new Long(10) };
|
||||
|
||||
return Arrays.<Number[]> asList(longToInt, atomicIntToInt, atomicIntToDouble, atomicLongToInt, atomicLongToLong);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1288
|
||||
*/
|
||||
@Test
|
||||
public void convertsToTargetTypeCorrectly() {
|
||||
assertThat(NumberToNumberConverterFactory.INSTANCE.getConverter(expected.getClass()).convert(source), is(expected));
|
||||
}
|
||||
}
|
||||
@@ -775,21 +775,6 @@ public class QueryMapperUnitTests {
|
||||
assertThat(dbo, isBsonObject().containing("geoJsonPoint.$geoWithin.$geometry.type", "Polygon"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1134
|
||||
*/
|
||||
@Test
|
||||
public void intersectsShouldUseGeoJsonRepresentationCorrectly() {
|
||||
|
||||
Query query = query(where("geoJsonPoint").intersects(
|
||||
new GeoJsonPolygon(new Point(0, 0), new Point(100, 100), new Point(100, 0), new Point(0, 0))));
|
||||
|
||||
DBObject dbo = mapper.getMappedObject(query.getQueryObject(), context.getPersistentEntity(ClassWithGeoTypes.class));
|
||||
|
||||
assertThat(dbo, isBsonObject().containing("geoJsonPoint.$geoIntersects.$geometry.type", "Polygon"));
|
||||
assertThat(dbo, isBsonObject().containing("geoJsonPoint.$geoIntersects.$geometry.coordinates"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1269
|
||||
*/
|
||||
|
||||
@@ -27,11 +27,9 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.hamcrest.Matcher;
|
||||
import org.hamcrest.collection.IsIterableContainingInOrder;
|
||||
import org.hamcrest.core.Is;
|
||||
import org.hamcrest.core.IsEqual;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -796,7 +794,7 @@ public class UpdateMapperUnitTests {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1251
|
||||
* see DATAMONGO-1251
|
||||
*/
|
||||
@Test
|
||||
public void mapsNullValueCorrectlyForSimpleTypes() {
|
||||
@@ -812,7 +810,7 @@ public class UpdateMapperUnitTests {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1251
|
||||
* see DATAMONGO-1251
|
||||
*/
|
||||
@Test
|
||||
public void mapsNullValueCorrectlyForJava8Date() {
|
||||
@@ -828,7 +826,7 @@ public class UpdateMapperUnitTests {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1251
|
||||
* see DATAMONGO-1251
|
||||
*/
|
||||
@Test
|
||||
public void mapsNullValueCorrectlyForCollectionTypes() {
|
||||
@@ -844,7 +842,7 @@ public class UpdateMapperUnitTests {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1251
|
||||
* see DATAMONGO-1251
|
||||
*/
|
||||
@Test
|
||||
public void mapsNullValueCorrectlyForPropertyOfNestedDocument() {
|
||||
@@ -859,34 +857,6 @@ public class UpdateMapperUnitTests {
|
||||
assertThat($set.get("concreteValue.name"), nullValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1288
|
||||
*/
|
||||
@Test
|
||||
public void mapsAtomicIntegerToIntegerCorrectly() {
|
||||
|
||||
Update update = new Update().set("intValue", new AtomicInteger(10));
|
||||
DBObject mappedUpdate = mapper.getMappedObject(update.getUpdateObject(),
|
||||
context.getPersistentEntity(SimpleValueHolder.class));
|
||||
|
||||
DBObject $set = DBObjectTestUtils.getAsDBObject(mappedUpdate, "$set");
|
||||
assertThat($set.get("intValue"), Is.<Object> is(10));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1288
|
||||
*/
|
||||
@Test
|
||||
public void mapsAtomicIntegerToPrimitiveIntegerCorrectly() {
|
||||
|
||||
Update update = new Update().set("primIntValue", new AtomicInteger(10));
|
||||
DBObject mappedUpdate = mapper.getMappedObject(update.getUpdateObject(),
|
||||
context.getPersistentEntity(SimpleValueHolder.class));
|
||||
|
||||
DBObject $set = DBObjectTestUtils.getAsDBObject(mappedUpdate, "$set");
|
||||
assertThat($set.get("primIntValue"), Is.<Object> is(10));
|
||||
}
|
||||
|
||||
static class DomainTypeWrappingConcreteyTypeHavingListOfInterfaceTypeAttributes {
|
||||
ListModelWrapper concreteTypeWithListAttributeOfInterfaceType;
|
||||
}
|
||||
@@ -1161,10 +1131,4 @@ public class UpdateMapperUnitTests {
|
||||
|
||||
LocalDate date;
|
||||
}
|
||||
|
||||
static class SimpleValueHolder {
|
||||
|
||||
Integer intValue;
|
||||
int primIntValue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2015 by the original author(s).
|
||||
* Copyright (c) 2011-2014 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.
|
||||
@@ -18,23 +18,15 @@ package org.springframework.data.mongodb.core.index;
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.mongodb.MongoDbFactory;
|
||||
import org.springframework.data.mongodb.core.CollectionCallback;
|
||||
import org.springframework.data.mongodb.core.MongoOperations;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
import org.springframework.data.mongodb.core.mapping.Field;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
@@ -47,15 +39,12 @@ import com.mongodb.MongoException;
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
* @author Jordi Llach
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration("classpath:infrastructure.xml")
|
||||
public class IndexingIntegrationTests {
|
||||
|
||||
@Autowired MongoOperations operations;
|
||||
@Autowired MongoDbFactory mongoDbFactory;
|
||||
@Autowired ConfigurableApplicationContext context;
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
@@ -63,40 +52,19 @@ public class IndexingIntegrationTests {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-237
|
||||
* @see DATADOC-237
|
||||
*/
|
||||
@Test
|
||||
@DirtiesContext
|
||||
public void createsIndexWithFieldName() {
|
||||
|
||||
operations.getConverter().getMappingContext().getPersistentEntity(IndexedPerson.class);
|
||||
|
||||
operations.save(new IndexedPerson());
|
||||
assertThat(hasIndex("_firstname", IndexedPerson.class), is(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1163
|
||||
*/
|
||||
@Test
|
||||
@DirtiesContext
|
||||
public void createsIndexFromMetaAnnotation() {
|
||||
|
||||
operations.getConverter().getMappingContext().getPersistentEntity(IndexedPerson.class);
|
||||
|
||||
assertThat(hasIndex("_lastname", IndexedPerson.class), is(true));
|
||||
}
|
||||
|
||||
@Target({ ElementType.FIELD })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Indexed
|
||||
@interface IndexedFieldAnnotation {
|
||||
}
|
||||
|
||||
@Document
|
||||
class IndexedPerson {
|
||||
|
||||
@Field("_firstname") @Indexed String firstname;
|
||||
@Field("_lastname") @IndexedFieldAnnotation String lastname;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,37 +18,25 @@ package org.springframework.data.mongodb.core.index;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
import org.hamcrest.core.IsInstanceOf;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.rules.RuleChain;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.domain.Sort.Direction;
|
||||
import org.springframework.data.mongodb.core.MongoOperations;
|
||||
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
|
||||
import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexResolver.IndexDefinitionHolder;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||
import org.springframework.data.mongodb.test.util.CleanMongoDB;
|
||||
import org.springframework.data.mongodb.test.util.MongoVersionRule;
|
||||
import org.springframework.data.util.Version;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import com.mongodb.MongoClient;
|
||||
import com.mongodb.MongoCommandException;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link MongoPersistentEntityIndexCreator}.
|
||||
*
|
||||
@@ -66,8 +54,6 @@ public class MongoPersistentEntityIndexCreatorIntegrationTests {
|
||||
public static @ClassRule RuleChain rules = RuleChain.outerRule(MongoVersionRule.atLeast(new Version(2, 6))).around(
|
||||
CleanMongoDB.indexes(Arrays.asList(SAMPLE_TYPE_COLLECTION_NAME, RECURSIVE_TYPE_COLLECTION_NAME)));
|
||||
|
||||
public @Rule ExpectedException expectedException = ExpectedException.none();
|
||||
|
||||
@Autowired @Qualifier("mongo1") MongoOperations templateOne;
|
||||
|
||||
@Autowired @Qualifier("mongo2") MongoOperations templateTwo;
|
||||
@@ -95,28 +81,6 @@ public class MongoPersistentEntityIndexCreatorIntegrationTests {
|
||||
assertThat(indexInfo, Matchers.<IndexInfo> hasItem(hasProperty("name", is("firstName"))));
|
||||
}
|
||||
|
||||
/**
|
||||
* @DATAMONGO-1125
|
||||
*/
|
||||
@Test
|
||||
public void createIndexShouldThrowMeaningfulExceptionWhenIndexCreationFails() throws UnknownHostException {
|
||||
|
||||
expectedException.expect(DataIntegrityViolationException.class);
|
||||
expectedException.expectMessage("collection 'datamongo-1125'");
|
||||
expectedException.expectMessage("dalinar.kohlin");
|
||||
expectedException.expectMessage("lastname");
|
||||
expectedException.expectCause(IsInstanceOf.<Throwable> instanceOf(MongoCommandException.class));
|
||||
|
||||
MongoPersistentEntityIndexCreator indexCreator = new MongoPersistentEntityIndexCreator(new MongoMappingContext(),
|
||||
new SimpleMongoDbFactory(new MongoClient(), "issue"));
|
||||
|
||||
indexCreator.createIndex(new IndexDefinitionHolder("dalinar.kohlin", new Index().named("stormlight")
|
||||
.on("lastname", Direction.ASC).unique(), "datamongo-1125"));
|
||||
|
||||
indexCreator.createIndex(new IndexDefinitionHolder("dalinar.kohlin", new Index().named("stormlight")
|
||||
.on("lastname", Direction.ASC).sparse(), "datamongo-1125"));
|
||||
}
|
||||
|
||||
@Document(collection = RECURSIVE_TYPE_COLLECTION_NAME)
|
||||
static abstract class RecursiveGenericType<RGT extends RecursiveGenericType<RGT>> {
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2015 the original author or authors.
|
||||
* Copyright 2012-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -28,14 +28,11 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.geo.Point;
|
||||
import org.springframework.data.mapping.context.MappingContextEvent;
|
||||
import org.springframework.data.mongodb.MongoDbFactory;
|
||||
import org.springframework.data.mongodb.core.MongoExceptionTranslator;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
import org.springframework.data.mongodb.core.mapping.Field;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||
@@ -46,7 +43,6 @@ import com.mongodb.BasicDBObjectBuilder;
|
||||
import com.mongodb.DB;
|
||||
import com.mongodb.DBCollection;
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.MongoException;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link MongoPersistentEntityIndexCreator}.
|
||||
@@ -215,36 +211,6 @@ public class MongoPersistentEntityIndexCreatorUnitTests {
|
||||
assertThat(collectionNameCapturer.getValue(), equalTo("indexedDocumentWrapper"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1125
|
||||
*/
|
||||
@Test(expected = DataAccessException.class)
|
||||
public void createIndexShouldUsePersistenceExceptionTranslatorForNonDataIntegrityConcerns() {
|
||||
|
||||
when(factory.getExceptionTranslator()).thenReturn(new MongoExceptionTranslator());
|
||||
doThrow(new MongoException(6, "HostUnreachable")).when(collection).createIndex(Mockito.any(DBObject.class),
|
||||
Mockito.any(DBObject.class));
|
||||
|
||||
MongoMappingContext mappingContext = prepareMappingContext(Person.class);
|
||||
|
||||
new MongoPersistentEntityIndexCreator(mappingContext, factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1125
|
||||
*/
|
||||
@Test(expected = ClassCastException.class)
|
||||
public void createIndexShouldNotConvertUnknownExceptionTypes() {
|
||||
|
||||
when(factory.getExceptionTranslator()).thenReturn(new MongoExceptionTranslator());
|
||||
doThrow(new ClassCastException("o_O")).when(collection).createIndex(Mockito.any(DBObject.class),
|
||||
Mockito.any(DBObject.class));
|
||||
|
||||
MongoMappingContext mappingContext = prepareMappingContext(Person.class);
|
||||
|
||||
new MongoPersistentEntityIndexCreator(mappingContext, factory);
|
||||
}
|
||||
|
||||
private static MongoMappingContext prepareMappingContext(Class<?> type) {
|
||||
|
||||
MongoMappingContext mappingContext = new MongoMappingContext();
|
||||
|
||||
@@ -19,10 +19,6 @@ import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@@ -181,21 +177,6 @@ public class MongoPersistentEntityIndexResolverUnitTests {
|
||||
equalTo(new BasicDBObjectBuilder().add("nested.indexedDbRef", 1).get()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1163
|
||||
*/
|
||||
@Test
|
||||
public void resolveIndexDefinitionInMetaAnnotatedFields() {
|
||||
|
||||
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
|
||||
IndexOnMetaAnnotatedField.class);
|
||||
|
||||
assertThat(indexDefinitions, hasSize(1));
|
||||
assertThat(indexDefinitions.get(0).getCollection(), equalTo("indexOnMetaAnnotatedField"));
|
||||
assertThat(indexDefinitions.get(0).getIndexOptions(),
|
||||
equalTo(new BasicDBObjectBuilder().add("name", "_name").get()));
|
||||
}
|
||||
|
||||
@Document(collection = "Zero")
|
||||
static class IndexOnLevelZero {
|
||||
@Indexed String indexedProperty;
|
||||
@@ -250,18 +231,6 @@ public class MongoPersistentEntityIndexResolverUnitTests {
|
||||
|
||||
}
|
||||
|
||||
@Target({ ElementType.FIELD })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Indexed
|
||||
@interface IndexedFieldAnnotation {
|
||||
|
||||
}
|
||||
|
||||
@Document
|
||||
static class IndexOnMetaAnnotatedField {
|
||||
@Field("_name") @IndexedFieldAnnotation String lastname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test resolution of {@link GeoSpatialIndexed}.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2015 by the original author(s).
|
||||
* Copyright (c) 2011 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.
|
||||
@@ -16,15 +16,14 @@
|
||||
|
||||
package org.springframework.data.mongodb.core.mapping;
|
||||
|
||||
import com.querydsl.core.annotations.QuerySupertype;
|
||||
import com.mysema.query.annotations.QuerySupertype;
|
||||
|
||||
/**
|
||||
* {@link QuerySupertype} is necessary for Querydsl 2.2.0-beta4 to compile the query classes directly. Can be removed as
|
||||
* soon as {@link https://bugs.launchpad.net/querydsl/+bug/776219} is fixed.
|
||||
*
|
||||
* @see https://bugs.launchpad.net/querydsl/+bug/776219
|
||||
* @author Jon Brisbin
|
||||
* @author Oliver Gierke
|
||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||
*/
|
||||
@QuerySupertype
|
||||
public abstract class BasePerson {
|
||||
@@ -33,7 +32,8 @@ public abstract class BasePerson {
|
||||
protected String firstName;
|
||||
protected String lastName;
|
||||
|
||||
public BasePerson() {}
|
||||
public BasePerson() {
|
||||
}
|
||||
|
||||
public BasePerson(Integer ssn, String firstName, String lastName) {
|
||||
this.ssn = ssn;
|
||||
|
||||
@@ -19,11 +19,6 @@ import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
@@ -231,18 +226,6 @@ public class BasicMongoPersistentEntityUnitTests {
|
||||
verify(dbRefMock, times(1)).lazy();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1291
|
||||
*/
|
||||
@Test
|
||||
public void metaInformationShouldBeReadCorrectlyFromInheritedDocumentAnnotation() {
|
||||
|
||||
BasicMongoPersistentEntity<DocumentWithCustomAnnotation> entity = new BasicMongoPersistentEntity<DocumentWithCustomAnnotation>(
|
||||
ClassTypeInformation.from(DocumentWithCustomAnnotation.class));
|
||||
|
||||
assertThat(entity.getCollection(), is("collection-1"));
|
||||
}
|
||||
|
||||
@Document(collection = "contacts")
|
||||
class Contact {
|
||||
|
||||
@@ -278,15 +261,4 @@ public class BasicMongoPersistentEntityUnitTests {
|
||||
static class AnyDocument {
|
||||
|
||||
}
|
||||
|
||||
@CustomDocumentAnnotation
|
||||
static class DocumentWithCustomAnnotation {
|
||||
|
||||
}
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.TYPE })
|
||||
@Document(collection = "collection-1")
|
||||
static @interface CustomDocumentAnnotation {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ public class AbstractMongoEventListenerUnitTests {
|
||||
@Test
|
||||
public void invokesCallbackForEventForPerson() {
|
||||
|
||||
MongoMappingEvent<Person> event = new BeforeConvertEvent<Person>(new Person("Dave", "Matthews"), "collection-1");
|
||||
MongoMappingEvent<Person> event = new BeforeConvertEvent<Person>(new Person("Dave", "Matthews"));
|
||||
SamplePersonEventListener listener = new SamplePersonEventListener();
|
||||
listener.onApplicationEvent(event);
|
||||
assertThat(listener.invokedOnBeforeConvert, is(true));
|
||||
@@ -54,11 +54,11 @@ public class AbstractMongoEventListenerUnitTests {
|
||||
SamplePersonEventListener listener = new SamplePersonEventListener();
|
||||
context.addApplicationListener(listener);
|
||||
|
||||
context.publishEvent(new BeforeConvertEvent<Person>(new Person("Dave", "Matthews"), "collection-1"));
|
||||
context.publishEvent(new BeforeConvertEvent<Person>(new Person("Dave", "Matthews")));
|
||||
assertThat(listener.invokedOnBeforeConvert, is(true));
|
||||
|
||||
listener.invokedOnBeforeConvert = false;
|
||||
context.publishEvent(new BeforeConvertEvent<String>("Test", "collection-1"));
|
||||
context.publishEvent(new BeforeConvertEvent<String>("Test"));
|
||||
assertThat(listener.invokedOnBeforeConvert, is(false));
|
||||
|
||||
context.close();
|
||||
@@ -71,7 +71,7 @@ public class AbstractMongoEventListenerUnitTests {
|
||||
public void afterLoadEffectGetsHandledCorrectly() {
|
||||
|
||||
SamplePersonEventListener listener = new SamplePersonEventListener();
|
||||
listener.onApplicationEvent(new AfterLoadEvent<Person>(new BasicDBObject(), Person.class, "collection-1"));
|
||||
listener.onApplicationEvent(new AfterLoadEvent<Person>(new BasicDBObject(), Person.class));
|
||||
assertThat(listener.invokedOnAfterLoad, is(true));
|
||||
}
|
||||
|
||||
@@ -83,8 +83,8 @@ public class AbstractMongoEventListenerUnitTests {
|
||||
|
||||
SamplePersonEventListener personListener = new SamplePersonEventListener();
|
||||
SampleAccountEventListener accountListener = new SampleAccountEventListener();
|
||||
personListener.onApplicationEvent(new AfterLoadEvent<Person>(new BasicDBObject(), Person.class, "collection-1"));
|
||||
accountListener.onApplicationEvent(new AfterLoadEvent<Person>(new BasicDBObject(), Person.class, "collection-1"));
|
||||
personListener.onApplicationEvent(new AfterLoadEvent<Person>(new BasicDBObject(), Person.class));
|
||||
accountListener.onApplicationEvent(new AfterLoadEvent<Person>(new BasicDBObject(), Person.class));
|
||||
|
||||
assertThat(personListener.invokedOnAfterLoad, is(true));
|
||||
assertThat(accountListener.invokedOnAfterLoad, is(false));
|
||||
@@ -98,8 +98,8 @@ public class AbstractMongoEventListenerUnitTests {
|
||||
|
||||
SamplePersonEventListener personListener = new SamplePersonEventListener();
|
||||
SampleContactEventListener contactListener = new SampleContactEventListener();
|
||||
personListener.onApplicationEvent(new AfterLoadEvent<Person>(new BasicDBObject(), Person.class, "collection-1"));
|
||||
contactListener.onApplicationEvent(new AfterLoadEvent<Person>(new BasicDBObject(), Person.class, "collection-1"));
|
||||
personListener.onApplicationEvent(new AfterLoadEvent<Person>(new BasicDBObject(), Person.class));
|
||||
contactListener.onApplicationEvent(new AfterLoadEvent<Person>(new BasicDBObject(), Person.class));
|
||||
|
||||
assertThat(personListener.invokedOnAfterLoad, is(true));
|
||||
assertThat(contactListener.invokedOnAfterLoad, is(true));
|
||||
@@ -113,8 +113,8 @@ public class AbstractMongoEventListenerUnitTests {
|
||||
|
||||
SamplePersonEventListener personListener = new SamplePersonEventListener();
|
||||
SampleContactEventListener contactListener = new SampleContactEventListener();
|
||||
personListener.onApplicationEvent(new AfterLoadEvent<Contact>(new BasicDBObject(), Contact.class, "collection-1"));
|
||||
contactListener.onApplicationEvent(new AfterLoadEvent<Contact>(new BasicDBObject(), Contact.class, "collection-1"));
|
||||
personListener.onApplicationEvent(new AfterLoadEvent<Contact>(new BasicDBObject(), Contact.class));
|
||||
contactListener.onApplicationEvent(new AfterLoadEvent<Contact>(new BasicDBObject(), Contact.class));
|
||||
|
||||
assertThat(personListener.invokedOnAfterLoad, is(false));
|
||||
assertThat(contactListener.invokedOnAfterLoad, is(true));
|
||||
@@ -137,7 +137,7 @@ public class AbstractMongoEventListenerUnitTests {
|
||||
@Test
|
||||
public void invokeContactCallbackForPersonEvent() {
|
||||
|
||||
MongoMappingEvent<DBObject> event = new BeforeDeleteEvent<Person>(new BasicDBObject(), Person.class, "collection-1");
|
||||
MongoMappingEvent<DBObject> event = new BeforeDeleteEvent<Person>(new BasicDBObject(), Person.class);
|
||||
SampleContactEventListener listener = new SampleContactEventListener();
|
||||
listener.onApplicationEvent(event);
|
||||
|
||||
@@ -150,7 +150,7 @@ public class AbstractMongoEventListenerUnitTests {
|
||||
@Test
|
||||
public void invokePersonCallbackForPersonEvent() {
|
||||
|
||||
MongoMappingEvent<DBObject> event = new BeforeDeleteEvent<Person>(new BasicDBObject(), Person.class, "collection-1");
|
||||
MongoMappingEvent<DBObject> event = new BeforeDeleteEvent<Person>(new BasicDBObject(), Person.class);
|
||||
SamplePersonEventListener listener = new SamplePersonEventListener();
|
||||
listener.onApplicationEvent(event);
|
||||
|
||||
@@ -163,8 +163,7 @@ public class AbstractMongoEventListenerUnitTests {
|
||||
@Test
|
||||
public void dontInvokePersonCallbackForAccountEvent() {
|
||||
|
||||
MongoMappingEvent<DBObject> event = new BeforeDeleteEvent<Account>(new BasicDBObject(), Account.class,
|
||||
"collection-1");
|
||||
MongoMappingEvent<DBObject> event = new BeforeDeleteEvent<Account>(new BasicDBObject(), Account.class);
|
||||
SamplePersonEventListener listener = new SamplePersonEventListener();
|
||||
listener.onApplicationEvent(event);
|
||||
|
||||
@@ -177,7 +176,7 @@ public class AbstractMongoEventListenerUnitTests {
|
||||
@Test
|
||||
public void donInvokePersonCallbackForUntypedEvent() {
|
||||
|
||||
MongoMappingEvent<DBObject> event = new BeforeDeleteEvent<Account>(new BasicDBObject(), null, "collection-1");
|
||||
MongoMappingEvent<DBObject> event = new BeforeDeleteEvent<Account>(new BasicDBObject(), null);
|
||||
SamplePersonEventListener listener = new SamplePersonEventListener();
|
||||
listener.onApplicationEvent(event);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011-2015 by the original author(s).
|
||||
* Copyright (c) 2011 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,10 +15,7 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.mapping.event;
|
||||
|
||||
import static org.hamcrest.core.Is.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.data.mongodb.core.query.Criteria.*;
|
||||
import static org.springframework.data.mongodb.core.query.Query.*;
|
||||
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
@@ -29,7 +26,6 @@ import org.junit.Test;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.data.mongodb.core.aggregation.Aggregation;
|
||||
import org.springframework.data.mongodb.core.mapping.PersonPojoStringId;
|
||||
|
||||
import com.mongodb.DB;
|
||||
@@ -42,13 +38,10 @@ import com.mongodb.WriteConcern;
|
||||
* Integration test for Mapping Events.
|
||||
*
|
||||
* @author Mark Pollack
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class ApplicationContextEventTests {
|
||||
|
||||
private static final String COLLECTION_NAME = "personPojoStringId";
|
||||
|
||||
private final String[] collectionsToDrop = new String[] { COLLECTION_NAME };
|
||||
private final String[] collectionsToDrop = new String[] { "personPojoStringId" };
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
private MongoTemplate template;
|
||||
@@ -67,7 +60,6 @@ public class ApplicationContextEventTests {
|
||||
}
|
||||
|
||||
private void cleanDb() throws UnknownHostException {
|
||||
|
||||
Mongo mongo = new MongoClient();
|
||||
DB db = mongo.getDB("database");
|
||||
for (String coll : collectionsToDrop) {
|
||||
@@ -98,9 +90,6 @@ public class ApplicationContextEventTests {
|
||||
assertEquals(1, simpleMappingEventListener.onBeforeSaveEvents.size());
|
||||
assertEquals(1, simpleMappingEventListener.onAfterSaveEvents.size());
|
||||
|
||||
assertEquals(COLLECTION_NAME, simpleMappingEventListener.onBeforeSaveEvents.get(0).getCollectionName());
|
||||
assertEquals(COLLECTION_NAME, simpleMappingEventListener.onAfterSaveEvents.get(0).getCollectionName());
|
||||
|
||||
Assert.assertTrue(personBeforeSaveListener.seenEvents.get(0) instanceof BeforeSaveEvent<?>);
|
||||
Assert.assertTrue(afterSaveListener.seenEvents.get(0) instanceof AfterSaveEvent<?>);
|
||||
|
||||
@@ -117,75 +106,7 @@ public class ApplicationContextEventTests {
|
||||
dbo = beforeSaveEvent.getDBObject();
|
||||
|
||||
comparePersonAndDbo(p, p2, dbo);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1256
|
||||
*/
|
||||
@Test
|
||||
public void loadAndConvertEvents() {
|
||||
|
||||
SimpleMappingEventListener simpleMappingEventListener = applicationContext
|
||||
.getBean(SimpleMappingEventListener.class);
|
||||
|
||||
PersonPojoStringId entity = new PersonPojoStringId("1", "Text");
|
||||
template.insert(entity);
|
||||
|
||||
template.findOne(query(where("id").is(entity.getId())), PersonPojoStringId.class);
|
||||
|
||||
assertThat(simpleMappingEventListener.onAfterLoadEvents.size(), is(1));
|
||||
assertThat(simpleMappingEventListener.onAfterLoadEvents.get(0).getCollectionName(), is(COLLECTION_NAME));
|
||||
|
||||
assertThat(simpleMappingEventListener.onBeforeConvertEvents.size(), is(1));
|
||||
assertThat(simpleMappingEventListener.onBeforeConvertEvents.get(0).getCollectionName(), is(COLLECTION_NAME));
|
||||
|
||||
assertThat(simpleMappingEventListener.onAfterConvertEvents.size(), is(1));
|
||||
assertThat(simpleMappingEventListener.onAfterConvertEvents.get(0).getCollectionName(), is(COLLECTION_NAME));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1256
|
||||
*/
|
||||
@Test
|
||||
public void loadEventsOnAggregation() {
|
||||
|
||||
SimpleMappingEventListener simpleMappingEventListener = applicationContext
|
||||
.getBean(SimpleMappingEventListener.class);
|
||||
|
||||
template.insert(new PersonPojoStringId("1", "Text"));
|
||||
|
||||
template.aggregate(Aggregation.newAggregation(Aggregation.project("text")), PersonPojoStringId.class,
|
||||
PersonPojoStringId.class);
|
||||
|
||||
assertThat(simpleMappingEventListener.onAfterLoadEvents.size(), is(1));
|
||||
assertThat(simpleMappingEventListener.onAfterLoadEvents.get(0).getCollectionName(), is(COLLECTION_NAME));
|
||||
|
||||
assertThat(simpleMappingEventListener.onBeforeConvertEvents.size(), is(1));
|
||||
assertThat(simpleMappingEventListener.onBeforeConvertEvents.get(0).getCollectionName(), is(COLLECTION_NAME));
|
||||
|
||||
assertThat(simpleMappingEventListener.onAfterConvertEvents.size(), is(1));
|
||||
assertThat(simpleMappingEventListener.onAfterConvertEvents.get(0).getCollectionName(), is(COLLECTION_NAME));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1256
|
||||
*/
|
||||
@Test
|
||||
public void deleteEvents() {
|
||||
|
||||
SimpleMappingEventListener simpleMappingEventListener = applicationContext
|
||||
.getBean(SimpleMappingEventListener.class);
|
||||
|
||||
PersonPojoStringId entity = new PersonPojoStringId("1", "Text");
|
||||
template.insert(entity);
|
||||
|
||||
template.remove(entity);
|
||||
|
||||
assertThat(simpleMappingEventListener.onBeforeDeleteEvents.size(), is(1));
|
||||
assertThat(simpleMappingEventListener.onBeforeDeleteEvents.get(0).getCollectionName(), is(COLLECTION_NAME));
|
||||
|
||||
assertThat(simpleMappingEventListener.onAfterDeleteEvents.size(), is(1));
|
||||
assertThat(simpleMappingEventListener.onAfterDeleteEvents.get(0).getCollectionName(), is(COLLECTION_NAME));
|
||||
}
|
||||
|
||||
private void comparePersonAndDbo(PersonPojoStringId p, PersonPojoStringId p2, DBObject dbo) {
|
||||
|
||||
@@ -78,7 +78,7 @@ public class AuditingEventListenerUnitTests {
|
||||
public void triggersCreationMarkForObjectWithEmptyId() {
|
||||
|
||||
Sample sample = new Sample();
|
||||
listener.onApplicationEvent(new BeforeConvertEvent<Object>(sample, "collection-1"));
|
||||
listener.onApplicationEvent(new BeforeConvertEvent<Object>(sample));
|
||||
|
||||
verify(handler, times(1)).markCreated(sample);
|
||||
verify(handler, times(0)).markModified(any(Sample.class));
|
||||
@@ -92,7 +92,7 @@ public class AuditingEventListenerUnitTests {
|
||||
|
||||
Sample sample = new Sample();
|
||||
sample.id = "id";
|
||||
listener.onApplicationEvent(new BeforeConvertEvent<Object>(sample, "collection-1"));
|
||||
listener.onApplicationEvent(new BeforeConvertEvent<Object>(sample));
|
||||
|
||||
verify(handler, times(0)).markCreated(any(Sample.class));
|
||||
verify(handler, times(1)).markModified(sample);
|
||||
|
||||
@@ -21,6 +21,8 @@ import java.util.List;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.data.mongodb.core.mapping.PersonPojoStringId;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
public class PersonBeforeSaveListener extends AbstractMongoEventListener<PersonPojoStringId> {
|
||||
|
||||
public final List<ApplicationEvent> seenEvents = new ArrayList<ApplicationEvent>();
|
||||
@@ -30,7 +32,7 @@ public class PersonBeforeSaveListener extends AbstractMongoEventListener<PersonP
|
||||
* @see org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener#onBeforeSave(java.lang.Object, com.mongodb.DBObject)
|
||||
*/
|
||||
@Override
|
||||
public void onBeforeSave(BeforeSaveEvent<PersonPojoStringId> event) {
|
||||
seenEvents.add(event);
|
||||
public void onBeforeSave(PersonPojoStringId source, DBObject dbo) {
|
||||
seenEvents.add(new BeforeSaveEvent<PersonPojoStringId>(source, dbo));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011-2015 by the original author(s).
|
||||
* Copyright (c) 2011 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.
|
||||
@@ -17,12 +17,8 @@ package org.springframework.data.mongodb.core.mapping.event;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* @author Mark Pollak
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Leiter
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
public class SimpleMappingEventListener extends AbstractMongoEventListener<Object> {
|
||||
|
||||
public final ArrayList<BeforeConvertEvent<Object>> onBeforeConvertEvents = new ArrayList<BeforeConvertEvent<Object>>();
|
||||
@@ -30,41 +26,29 @@ public class SimpleMappingEventListener extends AbstractMongoEventListener<Objec
|
||||
public final ArrayList<AfterSaveEvent<Object>> onAfterSaveEvents = new ArrayList<AfterSaveEvent<Object>>();
|
||||
public final ArrayList<AfterLoadEvent<Object>> onAfterLoadEvents = new ArrayList<AfterLoadEvent<Object>>();
|
||||
public final ArrayList<AfterConvertEvent<Object>> onAfterConvertEvents = new ArrayList<AfterConvertEvent<Object>>();
|
||||
public final ArrayList<BeforeDeleteEvent<Object>> onBeforeDeleteEvents = new ArrayList<BeforeDeleteEvent<Object>>();
|
||||
public final ArrayList<AfterDeleteEvent<Object>> onAfterDeleteEvents = new ArrayList<AfterDeleteEvent<Object>>();
|
||||
|
||||
@Override
|
||||
public void onBeforeConvert(BeforeConvertEvent<Object> event) {
|
||||
onBeforeConvertEvents.add(event);
|
||||
public void onBeforeConvert(Object source) {
|
||||
onBeforeConvertEvents.add(new BeforeConvertEvent<Object>(source));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBeforeSave(BeforeSaveEvent<Object> event) {
|
||||
onBeforeSaveEvents.add(event);
|
||||
public void onBeforeSave(Object source, DBObject dbo) {
|
||||
onBeforeSaveEvents.add(new BeforeSaveEvent<Object>(source, dbo));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAfterSave(AfterSaveEvent<Object> event) {
|
||||
onAfterSaveEvents.add(event);
|
||||
public void onAfterSave(Object source, DBObject dbo) {
|
||||
onAfterSaveEvents.add(new AfterSaveEvent<Object>(source, dbo));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAfterLoad(AfterLoadEvent<Object> event) {
|
||||
onAfterLoadEvents.add(event);
|
||||
public void onAfterLoad(DBObject dbo) {
|
||||
onAfterLoadEvents.add(new AfterLoadEvent<Object>(dbo, Object.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAfterConvert(AfterConvertEvent<Object> event) {
|
||||
onAfterConvertEvents.add(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAfterDelete(AfterDeleteEvent<Object> event) {
|
||||
onAfterDeleteEvents.add(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBeforeDelete(BeforeDeleteEvent<Object> event) {
|
||||
onBeforeDeleteEvents.add(event);
|
||||
public void onAfterConvert(DBObject dbo, Object source) {
|
||||
onAfterConvertEvents.add(new AfterConvertEvent<Object>(dbo, source));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2014 the original author or authors.
|
||||
* Copyright 2011-2016 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.
|
||||
@@ -18,8 +18,7 @@ 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 nl.jqno.equalsverifier.EqualsVerifier;
|
||||
import nl.jqno.equalsverifier.Warning;
|
||||
import static org.springframework.data.mongodb.test.util.IsBsonObject.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.domain.Sort.Direction;
|
||||
@@ -27,11 +26,15 @@ import org.springframework.data.domain.Sort.Direction;
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
import nl.jqno.equalsverifier.EqualsVerifier;
|
||||
import nl.jqno.equalsverifier.Warning;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link BasicQuery}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Darimont
|
||||
* @author John Willemin
|
||||
*/
|
||||
public class BasicQueryUnitTests {
|
||||
|
||||
@@ -137,4 +140,48 @@ public class BasicQueryUnitTests {
|
||||
assertThat(query1, is(not(equalTo(query2))));
|
||||
assertThat(query1.hashCode(), is(not(query2.hashCode())));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1387
|
||||
*/
|
||||
@Test
|
||||
public void returnsFieldsCorrectly() {
|
||||
|
||||
String qry = "{ \"name\" : \"Thomas\"}";
|
||||
String fields = "{\"name\":1, \"age\":1}";
|
||||
|
||||
BasicQuery query1 = new BasicQuery(qry, fields);
|
||||
|
||||
assertThat(query1.getFieldsObject(), isBsonObject().containing("name").containing("age"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1387
|
||||
*/
|
||||
@Test
|
||||
public void handlesFieldsIncludeCorrectly() {
|
||||
|
||||
String qry = "{ \"name\" : \"Thomas\"}";
|
||||
|
||||
BasicQuery query1 = new BasicQuery(qry);
|
||||
query1.fields().include("name");
|
||||
|
||||
assertThat(query1.getFieldsObject(), isBsonObject().containing("name"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1387
|
||||
*/
|
||||
@Test
|
||||
public void combinesFieldsIncludeCorrectly() {
|
||||
|
||||
String qry = "{ \"name\" : \"Thomas\"}";
|
||||
String fields = "{\"name\":1, \"age\":1}";
|
||||
|
||||
BasicQuery query1 = new BasicQuery(qry, fields);
|
||||
query1.fields().include("gender");
|
||||
|
||||
assertThat(query1.getFieldsObject(), isBsonObject().containing("name").containing("age").containing("gender"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2015 the original author or authors.
|
||||
* Copyright 2010-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,13 +17,12 @@ package org.springframework.data.mongodb.core.query;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.data.mongodb.test.util.IsBsonObject.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.geo.Point;
|
||||
import org.springframework.data.mongodb.InvalidMongoDbApiUsageException;
|
||||
import org.springframework.data.mongodb.core.geo.GeoJsonLineString;
|
||||
import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
|
||||
import org.springframework.data.mongodb.test.util.IsBsonObject;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.BasicDBObjectBuilder;
|
||||
@@ -177,7 +176,7 @@ public class CriteriaTests {
|
||||
|
||||
DBObject dbo = new Criteria("foo").near(new GeoJsonPoint(100, 200)).getCriteriaObject();
|
||||
|
||||
assertThat(dbo, isBsonObject().containing("foo.$near.$geometry", new GeoJsonPoint(100, 200)));
|
||||
assertThat(dbo, IsBsonObject.isBsonObject().containing("foo.$near.$geometry", new GeoJsonPoint(100, 200)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -188,7 +187,7 @@ public class CriteriaTests {
|
||||
|
||||
DBObject dbo = new Criteria("foo").near(new Point(100, 200)).getCriteriaObject();
|
||||
|
||||
assertThat(dbo, isBsonObject().notContaining("foo.$near.$geometry"));
|
||||
assertThat(dbo, IsBsonObject.isBsonObject().notContaining("foo.$near.$geometry"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -199,7 +198,7 @@ public class CriteriaTests {
|
||||
|
||||
DBObject dbo = new Criteria("foo").near(new GeoJsonPoint(100, 200)).maxDistance(50D).getCriteriaObject();
|
||||
|
||||
assertThat(dbo, isBsonObject().containing("foo.$near.$maxDistance", 50D));
|
||||
assertThat(dbo, IsBsonObject.isBsonObject().containing("foo.$near.$maxDistance", 50D));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -210,7 +209,7 @@ public class CriteriaTests {
|
||||
|
||||
DBObject dbo = new Criteria("foo").nearSphere(new GeoJsonPoint(100, 200)).maxDistance(50D).getCriteriaObject();
|
||||
|
||||
assertThat(dbo, isBsonObject().containing("foo.$nearSphere.$maxDistance", 50D));
|
||||
assertThat(dbo, IsBsonObject.isBsonObject().containing("foo.$nearSphere.$maxDistance", 50D));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -221,7 +220,7 @@ public class CriteriaTests {
|
||||
|
||||
DBObject dbo = new Criteria("foo").near(new GeoJsonPoint(100, 200)).minDistance(50D).getCriteriaObject();
|
||||
|
||||
assertThat(dbo, isBsonObject().containing("foo.$near.$minDistance", 50D));
|
||||
assertThat(dbo, IsBsonObject.isBsonObject().containing("foo.$near.$minDistance", 50D));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -232,7 +231,7 @@ public class CriteriaTests {
|
||||
|
||||
DBObject dbo = new Criteria("foo").nearSphere(new GeoJsonPoint(100, 200)).minDistance(50D).getCriteriaObject();
|
||||
|
||||
assertThat(dbo, isBsonObject().containing("foo.$nearSphere.$minDistance", 50D));
|
||||
assertThat(dbo, IsBsonObject.isBsonObject().containing("foo.$nearSphere.$minDistance", 50D));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -244,27 +243,8 @@ public class CriteriaTests {
|
||||
DBObject dbo = new Criteria("foo").nearSphere(new GeoJsonPoint(100, 200)).minDistance(50D).maxDistance(100D)
|
||||
.getCriteriaObject();
|
||||
|
||||
assertThat(dbo, isBsonObject().containing("foo.$nearSphere.$minDistance", 50D));
|
||||
assertThat(dbo, isBsonObject().containing("foo.$nearSphere.$maxDistance", 100D));
|
||||
assertThat(dbo, IsBsonObject.isBsonObject().containing("foo.$nearSphere.$minDistance", 50D));
|
||||
assertThat(dbo, IsBsonObject.isBsonObject().containing("foo.$nearSphere.$maxDistance", 100D));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1134
|
||||
*/
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void intersectsShouldThrowExceptionWhenCalledWihtNullValue() {
|
||||
new Criteria("foo").intersects(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1134
|
||||
*/
|
||||
@Test
|
||||
public void intersectsShouldWrapGeoJsonTypeInGeometryCorrectly() {
|
||||
|
||||
GeoJsonLineString lineString = new GeoJsonLineString(new Point(0, 0), new Point(10, 10));
|
||||
DBObject dbo = new Criteria("foo").intersects(lineString).getCriteriaObject();
|
||||
|
||||
assertThat(dbo, isBsonObject().containing("foo.$geoIntersects.$geometry", lineString));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +52,6 @@ import org.springframework.data.geo.Polygon;
|
||||
import org.springframework.data.mongodb.core.MongoOperations;
|
||||
import org.springframework.data.mongodb.core.query.BasicQuery;
|
||||
import org.springframework.data.mongodb.repository.Person.Sex;
|
||||
import org.springframework.data.mongodb.repository.SampleEvaluationContextExtension.SampleSecurityContextHolder;
|
||||
import org.springframework.data.querydsl.QSort;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
@@ -175,8 +174,8 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
|
||||
@Test
|
||||
public void executesPagedFinderCorrectly() throws Exception {
|
||||
|
||||
Page<Person> page = repository.findByLastnameLike("*a*",
|
||||
new PageRequest(0, 2, Direction.ASC, "lastname", "firstname"));
|
||||
Page<Person> page = repository.findByLastnameLike("*a*", new PageRequest(0, 2, Direction.ASC, "lastname",
|
||||
"firstname"));
|
||||
assertThat(page.isFirst(), is(true));
|
||||
assertThat(page.isLast(), is(false));
|
||||
assertThat(page.getNumberOfElements(), is(2));
|
||||
@@ -186,8 +185,8 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
|
||||
@Test
|
||||
public void executesPagedFinderWithAnnotatedQueryCorrectly() throws Exception {
|
||||
|
||||
Page<Person> page = repository.findByLastnameLikeWithPageable(".*a.*",
|
||||
new PageRequest(0, 2, Direction.ASC, "lastname", "firstname"));
|
||||
Page<Person> page = repository.findByLastnameLikeWithPageable(".*a.*", new PageRequest(0, 2, Direction.ASC,
|
||||
"lastname", "firstname"));
|
||||
assertThat(page.isFirst(), is(true));
|
||||
assertThat(page.isLast(), is(false));
|
||||
assertThat(page.getNumberOfElements(), is(2));
|
||||
@@ -311,8 +310,8 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
|
||||
@Test
|
||||
public void findsPagedPeopleByPredicate() throws Exception {
|
||||
|
||||
Page<Person> page = repository.findAll(person.lastname.contains("a"),
|
||||
new PageRequest(0, 2, Direction.ASC, "lastname"));
|
||||
Page<Person> page = repository.findAll(person.lastname.contains("a"), new PageRequest(0, 2, Direction.ASC,
|
||||
"lastname"));
|
||||
assertThat(page.isFirst(), is(true));
|
||||
assertThat(page.isLast(), is(false));
|
||||
assertThat(page.getNumberOfElements(), is(2));
|
||||
@@ -398,8 +397,8 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
|
||||
dave.setLocation(point);
|
||||
repository.save(dave);
|
||||
|
||||
GeoResults<Person> results = repository.findByLocationNear(new Point(-73.99, 40.73),
|
||||
new Distance(2000, Metrics.KILOMETERS));
|
||||
GeoResults<Person> results = repository.findByLocationNear(new Point(-73.99, 40.73), new Distance(2000,
|
||||
Metrics.KILOMETERS));
|
||||
assertThat(results.getContent().isEmpty(), is(false));
|
||||
}
|
||||
|
||||
@@ -410,8 +409,8 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
|
||||
dave.setLocation(point);
|
||||
repository.save(dave);
|
||||
|
||||
GeoPage<Person> results = repository.findByLocationNear(new Point(-73.99, 40.73),
|
||||
new Distance(2000, Metrics.KILOMETERS), new PageRequest(0, 20));
|
||||
GeoPage<Person> results = repository.findByLocationNear(new Point(-73.99, 40.73), new Distance(2000,
|
||||
Metrics.KILOMETERS), new PageRequest(0, 20));
|
||||
assertThat(results.getContent().isEmpty(), is(false));
|
||||
|
||||
// DATAMONGO-607
|
||||
@@ -621,8 +620,8 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
|
||||
|
||||
repository.save(Arrays.asList(dave, oliver, carter, boyd, leroi));
|
||||
|
||||
GeoPage<Person> results = repository.findByLocationNear(new Point(-73.99, 40.73),
|
||||
new Distance(2000, Metrics.KILOMETERS), new PageRequest(1, 2));
|
||||
GeoPage<Person> results = repository.findByLocationNear(new Point(-73.99, 40.73), new Distance(2000,
|
||||
Metrics.KILOMETERS), new PageRequest(1, 2));
|
||||
|
||||
assertThat(results.getContent().isEmpty(), is(false));
|
||||
assertThat(results.getNumberOfElements(), is(2));
|
||||
@@ -646,8 +645,8 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
|
||||
|
||||
repository.save(Arrays.asList(dave, oliver, carter));
|
||||
|
||||
GeoPage<Person> results = repository.findByLocationNear(new Point(-73.99, 40.73),
|
||||
new Distance(2000, Metrics.KILOMETERS), new PageRequest(1, 2));
|
||||
GeoPage<Person> results = repository.findByLocationNear(new Point(-73.99, 40.73), new Distance(2000,
|
||||
Metrics.KILOMETERS), new PageRequest(1, 2));
|
||||
assertThat(results.getContent().isEmpty(), is(false));
|
||||
assertThat(results.getNumberOfElements(), is(1));
|
||||
assertThat(results.isFirst(), is(false));
|
||||
@@ -665,8 +664,8 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
|
||||
dave.setLocation(point);
|
||||
repository.save(dave);
|
||||
|
||||
GeoPage<Person> results = repository.findByLocationNear(new Point(-73.99, 40.73),
|
||||
new Distance(2000, Metrics.KILOMETERS), new PageRequest(0, 2));
|
||||
GeoPage<Person> results = repository.findByLocationNear(new Point(-73.99, 40.73), new Distance(2000,
|
||||
Metrics.KILOMETERS), new PageRequest(0, 2));
|
||||
|
||||
assertThat(results.getContent().isEmpty(), is(false));
|
||||
assertThat(results.getNumberOfElements(), is(1));
|
||||
@@ -684,8 +683,8 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
|
||||
dave.setLocation(new Point(-73.99171, 40.738868));
|
||||
repository.save(dave);
|
||||
|
||||
GeoPage<Person> results = repository.findByLocationNear(new Point(-73.99, 40.73),
|
||||
new Distance(2000, Metrics.KILOMETERS), new PageRequest(1, 2));
|
||||
GeoPage<Person> results = repository.findByLocationNear(new Point(-73.99, 40.73), new Distance(2000,
|
||||
Metrics.KILOMETERS), new PageRequest(1, 2));
|
||||
|
||||
assertThat(results.getContent().isEmpty(), is(true));
|
||||
assertThat(results.getNumberOfElements(), is(0));
|
||||
@@ -935,8 +934,8 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
|
||||
@Test
|
||||
public void shouldLimitCollectionQueryToMaxResultsWhenPresent() {
|
||||
|
||||
repository.save(Arrays.asList(new Person("Bob-1", "Dylan"), new Person("Bob-2", "Dylan"),
|
||||
new Person("Bob-3", "Dylan"), new Person("Bob-4", "Dylan"), new Person("Bob-5", "Dylan")));
|
||||
repository.save(Arrays.asList(new Person("Bob-1", "Dylan"), new Person("Bob-2", "Dylan"), new Person("Bob-3",
|
||||
"Dylan"), new Person("Bob-4", "Dylan"), new Person("Bob-5", "Dylan")));
|
||||
List<Person> result = repository.findTop3ByLastnameStartingWith("Dylan");
|
||||
assertThat(result.size(), is(3));
|
||||
}
|
||||
@@ -947,8 +946,8 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
|
||||
@Test
|
||||
public void shouldNotLimitPagedQueryWhenPageRequestWithinBounds() {
|
||||
|
||||
repository.save(Arrays.asList(new Person("Bob-1", "Dylan"), new Person("Bob-2", "Dylan"),
|
||||
new Person("Bob-3", "Dylan"), new Person("Bob-4", "Dylan"), new Person("Bob-5", "Dylan")));
|
||||
repository.save(Arrays.asList(new Person("Bob-1", "Dylan"), new Person("Bob-2", "Dylan"), new Person("Bob-3",
|
||||
"Dylan"), new Person("Bob-4", "Dylan"), new Person("Bob-5", "Dylan")));
|
||||
Page<Person> result = repository.findTop3ByLastnameStartingWith("Dylan", new PageRequest(0, 2));
|
||||
assertThat(result.getContent().size(), is(2));
|
||||
}
|
||||
@@ -959,8 +958,8 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
|
||||
@Test
|
||||
public void shouldLimitPagedQueryWhenPageRequestExceedsUpperBoundary() {
|
||||
|
||||
repository.save(Arrays.asList(new Person("Bob-1", "Dylan"), new Person("Bob-2", "Dylan"),
|
||||
new Person("Bob-3", "Dylan"), new Person("Bob-4", "Dylan"), new Person("Bob-5", "Dylan")));
|
||||
repository.save(Arrays.asList(new Person("Bob-1", "Dylan"), new Person("Bob-2", "Dylan"), new Person("Bob-3",
|
||||
"Dylan"), new Person("Bob-4", "Dylan"), new Person("Bob-5", "Dylan")));
|
||||
Page<Person> result = repository.findTop3ByLastnameStartingWith("Dylan", new PageRequest(1, 2));
|
||||
assertThat(result.getContent().size(), is(1));
|
||||
}
|
||||
@@ -971,8 +970,8 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
|
||||
@Test
|
||||
public void shouldReturnEmptyWhenPageRequestedPageIsTotallyOutOfScopeForLimit() {
|
||||
|
||||
repository.save(Arrays.asList(new Person("Bob-1", "Dylan"), new Person("Bob-2", "Dylan"),
|
||||
new Person("Bob-3", "Dylan"), new Person("Bob-4", "Dylan"), new Person("Bob-5", "Dylan")));
|
||||
repository.save(Arrays.asList(new Person("Bob-1", "Dylan"), new Person("Bob-2", "Dylan"), new Person("Bob-3",
|
||||
"Dylan"), new Person("Bob-4", "Dylan"), new Person("Bob-5", "Dylan")));
|
||||
Page<Person> result = repository.findTop3ByLastnameStartingWith("Dylan", new PageRequest(2, 2));
|
||||
assertThat(result.getContent().size(), is(0));
|
||||
}
|
||||
@@ -1184,41 +1183,4 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
|
||||
GeoResults<Person> results = repository.findPersonByLocationNear(new Point(-73.99, 40.73), range);
|
||||
assertThat(results.getContent().isEmpty(), is(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-990
|
||||
*/
|
||||
@Test
|
||||
public void shouldFindByFirstnameForSpELExpressionWithParameterIndexOnly() {
|
||||
|
||||
List<Person> users = repository.findWithSpelByFirstnameForSpELExpressionWithParameterIndexOnly("Dave");
|
||||
|
||||
assertThat(users, hasSize(1));
|
||||
assertThat(users.get(0), is(dave));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-990
|
||||
*/
|
||||
@Test
|
||||
public void shouldFindByFirstnameAndCurrentUserWithCustomQuery() {
|
||||
|
||||
SampleSecurityContextHolder.getCurrent().setPrincipal(dave);
|
||||
List<Person> users = repository.findWithSpelByFirstnameAndCurrentUserWithCustomQuery("Dave");
|
||||
|
||||
assertThat(users, hasSize(1));
|
||||
assertThat(users.get(0), is(dave));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-990
|
||||
*/
|
||||
@Test
|
||||
public void shouldFindByFirstnameForSpELExpressionWithParameterVariableOnly() {
|
||||
|
||||
List<Person> users = repository.findWithSpelByFirstnameForSpELExpressionWithParameterVariableOnly("Dave");
|
||||
|
||||
assertThat(users, hasSize(1));
|
||||
assertThat(users.get(0), is(dave));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2015 the original author or authors.
|
||||
* 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.
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.repository;
|
||||
|
||||
import com.querydsl.core.annotations.QueryEmbeddable;
|
||||
import com.mysema.query.annotations.QueryEmbeddable;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
|
||||
@@ -34,7 +34,6 @@ import org.springframework.data.geo.Point;
|
||||
import org.springframework.data.geo.Polygon;
|
||||
import org.springframework.data.mongodb.repository.Person.Sex;
|
||||
import org.springframework.data.querydsl.QueryDslPredicateExecutor;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
/**
|
||||
* Sample repository managing {@link Person} entities.
|
||||
@@ -334,22 +333,4 @@ public interface PersonRepository extends MongoRepository<Person, String>, Query
|
||||
*/
|
||||
@Query("{ firstname : { $in : ?0 }}")
|
||||
Stream<Person> findByCustomQueryWithStreamingCursorByFirstnames(List<String> firstnames);
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-990
|
||||
*/
|
||||
@Query("{ firstname : ?#{[0]}}")
|
||||
List<Person> findWithSpelByFirstnameForSpELExpressionWithParameterIndexOnly(String firstname);
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-990
|
||||
*/
|
||||
@Query("{ firstname : ?#{[0]}, email: ?#{principal.email} }")
|
||||
List<Person> findWithSpelByFirstnameAndCurrentUserWithCustomQuery(String firstname);
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-990
|
||||
*/
|
||||
@Query("{ firstname : :#{#firstname}}")
|
||||
List<Person> findWithSpelByFirstnameForSpELExpressionWithParameterVariableOnly(@Param("firstname") String firstname);
|
||||
}
|
||||
|
||||
@@ -1,124 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 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;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.data.repository.query.spi.EvaluationContextExtension;
|
||||
import org.springframework.data.repository.query.spi.EvaluationContextExtensionSupport;
|
||||
|
||||
/**
|
||||
* A sample implementation of a custom {@link EvaluationContextExtension}.
|
||||
*
|
||||
* @author Thomas Darimont
|
||||
*/
|
||||
public class SampleEvaluationContextExtension extends EvaluationContextExtensionSupport {
|
||||
|
||||
@Override
|
||||
public String getExtensionId() {
|
||||
return "security";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getProperties() {
|
||||
return Collections.singletonMap("principal", SampleSecurityContextHolder.getCurrent().getPrincipal());
|
||||
}
|
||||
|
||||
/**
|
||||
* @author Thomas Darimont
|
||||
*/
|
||||
public static class SampleSecurityContextHolder {
|
||||
|
||||
private static ThreadLocal<SampleAuthentication> auth = new ThreadLocal<SampleAuthentication>() {
|
||||
|
||||
protected SampleAuthentication initialValue() {
|
||||
return new SampleAuthentication(new SampleUser(-1, "anonymous"));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
public static SampleAuthentication getCurrent() {
|
||||
return auth.get();
|
||||
}
|
||||
|
||||
public static void clear() {
|
||||
auth.remove();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @author Thomas Darimont
|
||||
*/
|
||||
public static class SampleAuthentication {
|
||||
|
||||
private Object principal;
|
||||
|
||||
public SampleAuthentication(Object principal) {
|
||||
this.principal = principal;
|
||||
}
|
||||
|
||||
public Object getPrincipal() {
|
||||
return principal;
|
||||
}
|
||||
|
||||
public void setPrincipal(Object principal) {
|
||||
this.principal = principal;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @author Thomas Darimont
|
||||
*/
|
||||
public static class SampleUser {
|
||||
|
||||
private Object id;
|
||||
private String name;
|
||||
|
||||
public SampleUser(Object id, String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Object getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Object id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public SampleUser withName(String name) {
|
||||
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SampleUser withId(Object id) {
|
||||
|
||||
this.id = id;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,7 +45,8 @@ public class MongoNamespaceIntegrationTests extends AbstractPersonRepositoryInte
|
||||
DefaultListableBeanFactory factory;
|
||||
BeanDefinitionReader reader;
|
||||
|
||||
@Autowired ApplicationContext context;
|
||||
@Autowired
|
||||
ApplicationContext context;
|
||||
|
||||
@Before
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
* Copyright 2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -53,9 +53,7 @@ import org.springframework.data.mongodb.core.query.BasicQuery;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.data.mongodb.repository.Meta;
|
||||
import org.springframework.data.mongodb.repository.MongoRepository;
|
||||
import org.springframework.data.projection.ProjectionFactory;
|
||||
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
|
||||
import org.springframework.data.repository.core.support.DefaultRepositoryMetadata;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
|
||||
import com.mongodb.BasicDBObjectBuilder;
|
||||
import com.mongodb.DBObject;
|
||||
@@ -66,28 +64,31 @@ import com.mongodb.WriteResult;
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Darimont
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class AbstractMongoQueryUnitTests {
|
||||
|
||||
@Mock RepositoryMetadata metadataMock;
|
||||
@Mock MongoOperations mongoOperationsMock;
|
||||
@Mock BasicMongoPersistentEntity<?> persitentEntityMock;
|
||||
@Mock @SuppressWarnings("rawtypes") BasicMongoPersistentEntity persitentEntityMock;
|
||||
@Mock MongoMappingContext mappingContextMock;
|
||||
@Mock WriteResult writeResultMock;
|
||||
|
||||
@Before
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public void setUp() {
|
||||
|
||||
doReturn("persons").when(persitentEntityMock).getCollection();
|
||||
doReturn(persitentEntityMock).when(mappingContextMock).getPersistentEntity(Matchers.any(Class.class));
|
||||
doReturn(Person.class).when(persitentEntityMock).getType();
|
||||
when(metadataMock.getDomainType()).thenReturn((Class) Person.class);
|
||||
when(metadataMock.getReturnedDomainClass(Matchers.any(Method.class))).thenReturn((Class) Person.class);
|
||||
when(persitentEntityMock.getCollection()).thenReturn("persons");
|
||||
when(mappingContextMock.getPersistentEntity(Matchers.any(Class.class))).thenReturn(persitentEntityMock);
|
||||
when(persitentEntityMock.getType()).thenReturn(Person.class);
|
||||
|
||||
DbRefResolver dbRefResolver = new DefaultDbRefResolver(mock(MongoDbFactory.class));
|
||||
MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, mappingContextMock);
|
||||
converter.afterPropertiesSet();
|
||||
|
||||
doReturn(converter).when(mongoOperationsMock).getConverter();
|
||||
when(mongoOperationsMock.getConverter()).thenReturn(converter);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -99,8 +100,8 @@ public class AbstractMongoQueryUnitTests {
|
||||
|
||||
createQueryForMethod("deletePersonByLastname", String.class).setDeleteQuery(true).execute(new Object[] { "booh" });
|
||||
|
||||
verify(mongoOperationsMock, times(1)).remove(Matchers.any(Query.class), eq(Person.class), eq("persons"));
|
||||
verify(mongoOperationsMock, times(0)).find(Matchers.any(Query.class), Matchers.any(Class.class),
|
||||
verify(this.mongoOperationsMock, times(1)).remove(Matchers.any(Query.class), eq(Person.class), eq("persons"));
|
||||
verify(this.mongoOperationsMock, times(0)).find(Matchers.any(Query.class), Matchers.any(Class.class),
|
||||
Matchers.anyString());
|
||||
}
|
||||
|
||||
@@ -112,12 +113,13 @@ public class AbstractMongoQueryUnitTests {
|
||||
@Test
|
||||
public void testDeleteExecutionLoadsListOfRemovedDocumentsWhenReturnTypeIsCollectionLike() {
|
||||
|
||||
when(mongoOperationsMock.find(Matchers.any(Query.class), Matchers.any(Class.class), Matchers.anyString()))
|
||||
when(this.mongoOperationsMock.find(Matchers.any(Query.class), Matchers.any(Class.class), Matchers.anyString()))
|
||||
.thenReturn(Arrays.asList(new Person(new ObjectId(new Date()), "bar")));
|
||||
|
||||
createQueryForMethod("deleteByLastname", String.class).setDeleteQuery(true).execute(new Object[] { "booh" });
|
||||
|
||||
verify(mongoOperationsMock, times(1)).findAllAndRemove(Matchers.any(Query.class), eq(Person.class), eq("persons"));
|
||||
verify(this.mongoOperationsMock, times(1)).findAllAndRemove(Matchers.any(Query.class), eq(Person.class),
|
||||
eq("persons"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -140,14 +142,14 @@ public class AbstractMongoQueryUnitTests {
|
||||
public void testDeleteExecutionReturnsNrDocumentsDeletedFromWriteResult() {
|
||||
|
||||
when(writeResultMock.getN()).thenReturn(100);
|
||||
when(mongoOperationsMock.remove(Matchers.any(Query.class), eq(Person.class), eq("persons")))
|
||||
.thenReturn(writeResultMock);
|
||||
when(this.mongoOperationsMock.remove(Matchers.any(Query.class), eq(Person.class), eq("persons"))).thenReturn(
|
||||
writeResultMock);
|
||||
|
||||
MongoQueryFake query = createQueryForMethod("deletePersonByLastname", String.class);
|
||||
query.setDeleteQuery(true);
|
||||
|
||||
assertThat(query.execute(new Object[] { "fake" }), is((Object) 100L));
|
||||
verify(mongoOperationsMock, times(1)).remove(Matchers.any(Query.class), eq(Person.class), eq("persons"));
|
||||
verify(this.mongoOperationsMock, times(1)).remove(Matchers.any(Query.class), eq(Person.class), eq("persons"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -161,7 +163,7 @@ public class AbstractMongoQueryUnitTests {
|
||||
|
||||
ArgumentCaptor<Query> captor = ArgumentCaptor.forClass(Query.class);
|
||||
|
||||
verify(mongoOperationsMock, times(1)).find(captor.capture(), eq(Person.class), eq("persons"));
|
||||
verify(this.mongoOperationsMock, times(1)).find(captor.capture(), eq(Person.class), eq("persons"));
|
||||
|
||||
assertThat(captor.getValue().getMeta().getComment(), nullValue());
|
||||
}
|
||||
@@ -192,7 +194,7 @@ public class AbstractMongoQueryUnitTests {
|
||||
|
||||
ArgumentCaptor<Query> captor = ArgumentCaptor.forClass(Query.class);
|
||||
|
||||
verify(mongoOperationsMock, times(1)).count(captor.capture(), eq(Person.class), eq("persons"));
|
||||
verify(this.mongoOperationsMock, times(1)).count(captor.capture(), eq(Person.class), eq("persons"));
|
||||
assertThat(captor.getValue().getMeta().getComment(), is("comment"));
|
||||
}
|
||||
|
||||
@@ -226,7 +228,7 @@ public class AbstractMongoQueryUnitTests {
|
||||
|
||||
ArgumentCaptor<Query> captor = ArgumentCaptor.forClass(Query.class);
|
||||
|
||||
verify(mongoOperationsMock, times(2)).find(captor.capture(), eq(Person.class), eq("persons"));
|
||||
verify(this.mongoOperationsMock, times(2)).find(captor.capture(), eq(Person.class), eq("persons"));
|
||||
|
||||
assertThat(captor.getAllValues().get(0).getSkip(), is(0));
|
||||
assertThat(captor.getAllValues().get(1).getSkip(), is(10));
|
||||
@@ -247,7 +249,7 @@ public class AbstractMongoQueryUnitTests {
|
||||
|
||||
ArgumentCaptor<Query> captor = ArgumentCaptor.forClass(Query.class);
|
||||
|
||||
verify(mongoOperationsMock, times(2)).find(captor.capture(), eq(Person.class), eq("persons"));
|
||||
verify(this.mongoOperationsMock, times(2)).find(captor.capture(), eq(Person.class), eq("persons"));
|
||||
|
||||
assertThat(captor.getAllValues().get(0).getLimit(), is(11));
|
||||
assertThat(captor.getAllValues().get(1).getLimit(), is(11));
|
||||
@@ -268,7 +270,7 @@ public class AbstractMongoQueryUnitTests {
|
||||
|
||||
ArgumentCaptor<Query> captor = ArgumentCaptor.forClass(Query.class);
|
||||
|
||||
verify(mongoOperationsMock, times(2)).find(captor.capture(), eq(Person.class), eq("persons"));
|
||||
verify(this.mongoOperationsMock, times(2)).find(captor.capture(), eq(Person.class), eq("persons"));
|
||||
|
||||
DBObject expectedSortObject = new BasicDBObjectBuilder().add("bar", -1).get();
|
||||
assertThat(captor.getAllValues().get(0).getSortObject(), is(expectedSortObject));
|
||||
@@ -295,9 +297,7 @@ public class AbstractMongoQueryUnitTests {
|
||||
try {
|
||||
|
||||
Method method = Repo.class.getMethod(methodName, paramTypes);
|
||||
ProjectionFactory factory = new SpelAwareProxyProjectionFactory();
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, new DefaultRepositoryMetadata(Repo.class), factory,
|
||||
mappingContextMock);
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadataMock, mappingContextMock);
|
||||
|
||||
return new MongoQueryFake(queryMethod, mongoOperationsMock);
|
||||
|
||||
|
||||
@@ -30,8 +30,6 @@ import org.springframework.data.geo.Point;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||
import org.springframework.data.mongodb.core.query.TextCriteria;
|
||||
import org.springframework.data.mongodb.repository.Person;
|
||||
import org.springframework.data.projection.ProjectionFactory;
|
||||
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.core.support.DefaultRepositoryMetadata;
|
||||
@@ -44,16 +42,15 @@ import org.springframework.data.repository.core.support.DefaultRepositoryMetadat
|
||||
*/
|
||||
public class MongoParametersParameterAccessorUnitTests {
|
||||
|
||||
Distance DISTANCE = new Distance(2.5, Metrics.KILOMETERS);
|
||||
RepositoryMetadata metadata = new DefaultRepositoryMetadata(PersonRepository.class);
|
||||
MongoMappingContext context = new MongoMappingContext();
|
||||
ProjectionFactory factory = new SpelAwareProxyProjectionFactory();
|
||||
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();
|
||||
|
||||
@Test
|
||||
public void returnsNullForDistanceIfNoneAvailable() throws NoSuchMethodException, SecurityException {
|
||||
|
||||
Method method = PersonRepository.class.getMethod("findByLocationNear", Point.class);
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, factory, context);
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, context);
|
||||
|
||||
MongoParameterAccessor accessor = new MongoParametersParameterAccessor(queryMethod,
|
||||
new Object[] { new Point(10, 20) });
|
||||
@@ -64,10 +61,10 @@ 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, factory, context);
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, context);
|
||||
|
||||
MongoParameterAccessor accessor = new MongoParametersParameterAccessor(queryMethod,
|
||||
new Object[] { new Point(10, 20), DISTANCE });
|
||||
MongoParameterAccessor accessor = new MongoParametersParameterAccessor(queryMethod, new Object[] {
|
||||
new Point(10, 20), DISTANCE });
|
||||
assertThat(accessor.getDistanceRange().getUpperBound(), is(DISTANCE));
|
||||
}
|
||||
|
||||
@@ -78,10 +75,10 @@ public class MongoParametersParameterAccessorUnitTests {
|
||||
public void shouldReturnAsFullTextStringWhenNoneDefinedForMethod() throws NoSuchMethodException, SecurityException {
|
||||
|
||||
Method method = PersonRepository.class.getMethod("findByLocationNear", Point.class, Distance.class);
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, factory, context);
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, context);
|
||||
|
||||
MongoParameterAccessor accessor = new MongoParametersParameterAccessor(queryMethod,
|
||||
new Object[] { new Point(10, 20), DISTANCE });
|
||||
MongoParameterAccessor accessor = new MongoParametersParameterAccessor(queryMethod, new Object[] {
|
||||
new Point(10, 20), DISTANCE });
|
||||
assertThat(accessor.getFullText(), IsNull.nullValue());
|
||||
}
|
||||
|
||||
@@ -92,10 +89,10 @@ public class MongoParametersParameterAccessorUnitTests {
|
||||
public void shouldProperlyConvertTextCriteria() throws NoSuchMethodException, SecurityException {
|
||||
|
||||
Method method = PersonRepository.class.getMethod("findByFirstname", String.class, TextCriteria.class);
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, factory, context);
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, context);
|
||||
|
||||
MongoParameterAccessor accessor = new MongoParametersParameterAccessor(queryMethod,
|
||||
new Object[] { "spring", TextCriteria.forDefaultLanguage().matching("data") });
|
||||
MongoParameterAccessor accessor = new MongoParametersParameterAccessor(queryMethod, new Object[] { "spring",
|
||||
TextCriteria.forDefaultLanguage().matching("data") });
|
||||
assertThat(accessor.getFullText().getCriteriaObject().toString(),
|
||||
equalTo("{ \"$text\" : { \"$search\" : \"data\"}}"));
|
||||
}
|
||||
@@ -107,13 +104,13 @@ public class MongoParametersParameterAccessorUnitTests {
|
||||
public void shouldDetectMinAndMaxDistance() throws NoSuchMethodException, SecurityException {
|
||||
|
||||
Method method = PersonRepository.class.getMethod("findByLocationNear", Point.class, Range.class);
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, factory, context);
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, context);
|
||||
|
||||
Distance min = new Distance(10, Metrics.KILOMETERS);
|
||||
Distance max = new Distance(20, Metrics.KILOMETERS);
|
||||
|
||||
MongoParameterAccessor accessor = new MongoParametersParameterAccessor(queryMethod,
|
||||
new Object[] { new Point(10, 20), Distance.between(min, max) });
|
||||
MongoParameterAccessor accessor = new MongoParametersParameterAccessor(queryMethod, new Object[] {
|
||||
new Point(10, 20), Distance.between(min, max) });
|
||||
|
||||
Range<Distance> range = accessor.getDistanceRange();
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ package org.springframework.data.mongodb.repository.query;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Matchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.springframework.data.mongodb.core.query.Criteria.*;
|
||||
import static org.springframework.data.mongodb.core.query.Query.*;
|
||||
@@ -25,11 +26,16 @@ import static org.springframework.data.mongodb.repository.query.StubParameterAcc
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
import org.bson.types.ObjectId;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.mockito.stubbing.Answer;
|
||||
import org.springframework.data.domain.Range;
|
||||
import org.springframework.data.geo.Distance;
|
||||
import org.springframework.data.geo.Metrics;
|
||||
@@ -37,28 +43,21 @@ import org.springframework.data.geo.Point;
|
||||
import org.springframework.data.geo.Polygon;
|
||||
import org.springframework.data.geo.Shape;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mongodb.MongoDbFactory;
|
||||
import org.springframework.data.mongodb.core.Person;
|
||||
import org.springframework.data.mongodb.core.Venue;
|
||||
import org.springframework.data.mongodb.core.convert.DbRefResolver;
|
||||
import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver;
|
||||
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverter;
|
||||
import org.springframework.data.mongodb.core.index.GeoSpatialIndexType;
|
||||
import org.springframework.data.mongodb.core.index.GeoSpatialIndexed;
|
||||
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.mapping.MongoPersistentProperty;
|
||||
import org.springframework.data.mongodb.core.query.Criteria;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.core.support.DefaultRepositoryMetadata;
|
||||
import org.springframework.data.repository.query.parser.PartTree;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
|
||||
/**
|
||||
* Unit test for {@link MongoQueryCreator}.
|
||||
@@ -67,12 +66,14 @@ import com.mongodb.DBObject;
|
||||
* @author Thomas Darimont
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class MongoQueryCreatorUnitTests {
|
||||
|
||||
Method findByFirstname, findByFirstnameAndFriend, findByFirstnameNotNull;
|
||||
|
||||
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> context;
|
||||
MongoConverter converter;
|
||||
@Mock MongoConverter converter;
|
||||
|
||||
MappingContext<?, MongoPersistentProperty> context;
|
||||
|
||||
@Rule public ExpectedException expection = ExpectedException.none();
|
||||
|
||||
@@ -81,8 +82,11 @@ public class MongoQueryCreatorUnitTests {
|
||||
|
||||
context = new MongoMappingContext();
|
||||
|
||||
DbRefResolver resolver = new DefaultDbRefResolver(mock(MongoDbFactory.class));
|
||||
converter = new MappingMongoConverter(resolver, context);
|
||||
doAnswer(new Answer<Object>() {
|
||||
public Object answer(InvocationOnMock invocation) throws Throwable {
|
||||
return invocation.getArguments()[0];
|
||||
}
|
||||
}).when(converter).convertToMongoType(any(), Mockito.any(TypeInformation.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -133,8 +137,8 @@ public class MongoQueryCreatorUnitTests {
|
||||
Point point = new Point(10, 20);
|
||||
Distance distance = new Distance(2.5, Metrics.KILOMETERS);
|
||||
|
||||
Query query = query(
|
||||
where("location").nearSphere(point).maxDistance(distance.getNormalizedValue()).and("firstname").is("Dave"));
|
||||
Query query = query(where("location").nearSphere(point).maxDistance(distance.getNormalizedValue()).and("firstname")
|
||||
.is("Dave"));
|
||||
assertBindsDistanceToQuery(point, distance, query);
|
||||
}
|
||||
|
||||
@@ -144,8 +148,8 @@ public class MongoQueryCreatorUnitTests {
|
||||
Point point = new Point(10, 20);
|
||||
Distance distance = new Distance(2.5);
|
||||
|
||||
Query query = query(
|
||||
where("location").near(point).maxDistance(distance.getNormalizedValue()).and("firstname").is("Dave"));
|
||||
Query query = query(where("location").near(point).maxDistance(distance.getNormalizedValue()).and("firstname")
|
||||
.is("Dave"));
|
||||
assertBindsDistanceToQuery(point, distance, query);
|
||||
}
|
||||
|
||||
@@ -237,13 +241,14 @@ public class MongoQueryCreatorUnitTests {
|
||||
public void createsQueryReferencingADBRefCorrectly() {
|
||||
|
||||
User user = new User();
|
||||
user.id = new ObjectId();
|
||||
com.mongodb.DBRef dbref = new com.mongodb.DBRef("user", "id");
|
||||
when(converter.toDBRef(eq(user), Mockito.any(MongoPersistentProperty.class))).thenReturn(dbref);
|
||||
|
||||
PartTree tree = new PartTree("findByCreator", User.class);
|
||||
MongoQueryCreator creator = new MongoQueryCreator(tree, getAccessor(converter, user), context);
|
||||
DBObject queryObject = creator.createQuery().getQueryObject();
|
||||
Query query = creator.createQuery();
|
||||
|
||||
assertThat(queryObject.get("creator"), is((Object) user));
|
||||
assertThat(query, is(query(where("creator").is(dbref))));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -287,14 +292,16 @@ public class MongoQueryCreatorUnitTests {
|
||||
|
||||
private void assertBindsDistanceToQuery(Point point, Distance distance, Query reference) throws Exception {
|
||||
|
||||
when(converter.convertToMongoType("Dave")).thenReturn("Dave");
|
||||
|
||||
PartTree tree = new PartTree("findByLocationNearAndFirstname",
|
||||
org.springframework.data.mongodb.repository.Person.class);
|
||||
Method method = PersonRepository.class.getMethod("findByLocationNearAndFirstname", Point.class, Distance.class,
|
||||
String.class);
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, new DefaultRepositoryMetadata(PersonRepository.class),
|
||||
new SpelAwareProxyProjectionFactory(), new MongoMappingContext());
|
||||
MongoParameterAccessor accessor = new MongoParametersParameterAccessor(queryMethod,
|
||||
new Object[] { point, distance, "Dave" });
|
||||
new MongoMappingContext());
|
||||
MongoParameterAccessor accessor = new MongoParametersParameterAccessor(queryMethod, new Object[] { point, distance,
|
||||
"Dave" });
|
||||
|
||||
Query query = new MongoQueryCreator(tree, new ConvertingParameterAccessor(converter, accessor), context)
|
||||
.createQuery();
|
||||
@@ -675,8 +682,6 @@ public class MongoQueryCreatorUnitTests {
|
||||
|
||||
class User {
|
||||
|
||||
ObjectId id;
|
||||
|
||||
@Field("foo") String username;
|
||||
|
||||
@DBRef User creator;
|
||||
|
||||
@@ -36,8 +36,6 @@ import org.springframework.data.mongodb.repository.Address;
|
||||
import org.springframework.data.mongodb.repository.Contact;
|
||||
import org.springframework.data.mongodb.repository.Meta;
|
||||
import org.springframework.data.mongodb.repository.Person;
|
||||
import org.springframework.data.projection.ProjectionFactory;
|
||||
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.core.support.DefaultRepositoryMetadata;
|
||||
|
||||
@@ -59,7 +57,10 @@ public class MongoQueryMethodUnitTests {
|
||||
@Test
|
||||
public void detectsCollectionFromRepoTypeIfReturnTypeNotAssignable() throws Exception {
|
||||
|
||||
MongoQueryMethod queryMethod = queryMethod(SampleRepository.class, "method");
|
||||
Method method = SampleRepository.class.getMethod("method");
|
||||
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, new DefaultRepositoryMetadata(SampleRepository.class),
|
||||
context);
|
||||
MongoEntityMetadata<?> metadata = queryMethod.getEntityInformation();
|
||||
|
||||
assertThat(metadata.getJavaType(), is(typeCompatibleWith(Address.class)));
|
||||
@@ -69,7 +70,10 @@ public class MongoQueryMethodUnitTests {
|
||||
@Test
|
||||
public void detectsCollectionFromReturnTypeIfReturnTypeAssignable() throws Exception {
|
||||
|
||||
MongoQueryMethod queryMethod = queryMethod(SampleRepository2.class, "method");
|
||||
Method method = SampleRepository2.class.getMethod("method");
|
||||
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, new DefaultRepositoryMetadata(SampleRepository.class),
|
||||
context);
|
||||
MongoEntityMetadata<?> entityInformation = queryMethod.getEntityInformation();
|
||||
|
||||
assertThat(entityInformation.getJavaType(), is(typeCompatibleWith(Person.class)));
|
||||
@@ -79,44 +83,34 @@ public class MongoQueryMethodUnitTests {
|
||||
@Test
|
||||
public void discoversUserAsDomainTypeForGeoPageQueryMethod() throws Exception {
|
||||
|
||||
MongoQueryMethod queryMethod = queryMethod(PersonRepository.class, "findByLocationNear", Point.class,
|
||||
Distance.class, Pageable.class);
|
||||
MongoQueryMethod queryMethod = queryMethod("findByLocationNear", Point.class, Distance.class, Pageable.class);
|
||||
assertThat(queryMethod.isGeoNearQuery(), is(true));
|
||||
assertThat(queryMethod.isPageQuery(), is(true));
|
||||
|
||||
queryMethod = queryMethod(PersonRepository.class, "findByFirstname", String.class, Point.class);
|
||||
queryMethod = queryMethod("findByFirstname", String.class, Point.class);
|
||||
assertThat(queryMethod.isGeoNearQuery(), is(true));
|
||||
assertThat(queryMethod.isPageQuery(), is(false));
|
||||
assertThat(queryMethod.getEntityInformation().getJavaType(), is(typeCompatibleWith(User.class)));
|
||||
|
||||
assertThat(queryMethod(PersonRepository.class, "findByEmailAddress", String.class, Point.class).isGeoNearQuery(),
|
||||
is(true));
|
||||
assertThat(queryMethod(PersonRepository.class, "findByFirstname", String.class, Point.class).isGeoNearQuery(),
|
||||
is(true));
|
||||
assertThat(queryMethod(PersonRepository.class, "findByLastname", String.class, Point.class).isGeoNearQuery(),
|
||||
is(true));
|
||||
assertThat(queryMethod("findByEmailAddress", String.class, Point.class).isGeoNearQuery(), is(true));
|
||||
assertThat(queryMethod("findByFirstname", String.class, Point.class).isGeoNearQuery(), is(true));
|
||||
assertThat(queryMethod("findByLastname", String.class, Point.class).isGeoNearQuery(), is(true));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsGeoPageQueryWithoutPageable() throws Exception {
|
||||
queryMethod(PersonRepository.class, "findByLocationNear", Point.class, Distance.class);
|
||||
queryMethod("findByLocationNear", Point.class, Distance.class);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsNullMappingContext() throws Exception {
|
||||
|
||||
Method method = PersonRepository.class.getMethod("findByFirstname", String.class, Point.class);
|
||||
|
||||
new MongoQueryMethod(method, new DefaultRepositoryMetadata(PersonRepository.class),
|
||||
new SpelAwareProxyProjectionFactory(), null);
|
||||
new MongoQueryMethod(method, new DefaultRepositoryMetadata(PersonRepository.class), null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void considersMethodReturningGeoPageAsPagingMethod() throws Exception {
|
||||
|
||||
MongoQueryMethod method = queryMethod(PersonRepository.class, "findByLocationNear", Point.class, Distance.class,
|
||||
Pageable.class);
|
||||
|
||||
MongoQueryMethod method = queryMethod("findByLocationNear", Point.class, Distance.class, Pageable.class);
|
||||
assertThat(method.isPageQuery(), is(true));
|
||||
assertThat(method.isCollectionQuery(), is(false));
|
||||
}
|
||||
@@ -124,7 +118,8 @@ public class MongoQueryMethodUnitTests {
|
||||
@Test
|
||||
public void createsMongoQueryMethodObjectForMethodReturningAnInterface() throws Exception {
|
||||
|
||||
queryMethod(SampleRepository2.class, "methodReturningAnInterface");
|
||||
Method method = SampleRepository2.class.getMethod("methodReturningAnInterface");
|
||||
new MongoQueryMethod(method, new DefaultRepositoryMetadata(SampleRepository2.class), context);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -133,8 +128,7 @@ public class MongoQueryMethodUnitTests {
|
||||
@Test
|
||||
public void createsMongoQueryMethodWithEmptyMetaCorrectly() throws Exception {
|
||||
|
||||
MongoQueryMethod method = queryMethod(PersonRepository.class, "emptyMetaAnnotation");
|
||||
|
||||
MongoQueryMethod method = queryMethod("emptyMetaAnnotation");
|
||||
assertThat(method.hasQueryMetaAttributes(), is(true));
|
||||
assertThat(method.getQueryMetaAttributes().hasValues(), is(false));
|
||||
}
|
||||
@@ -145,8 +139,7 @@ public class MongoQueryMethodUnitTests {
|
||||
@Test
|
||||
public void createsMongoQueryMethodWithMaxExecutionTimeCorrectly() throws Exception {
|
||||
|
||||
MongoQueryMethod method = queryMethod(PersonRepository.class, "metaWithMaxExecutionTime");
|
||||
|
||||
MongoQueryMethod method = queryMethod("metaWithMaxExecutionTime");
|
||||
assertThat(method.hasQueryMetaAttributes(), is(true));
|
||||
assertThat(method.getQueryMetaAttributes().getMaxTimeMsec(), is(100L));
|
||||
}
|
||||
@@ -157,8 +150,7 @@ public class MongoQueryMethodUnitTests {
|
||||
@Test
|
||||
public void createsMongoQueryMethodWithMaxScanCorrectly() throws Exception {
|
||||
|
||||
MongoQueryMethod method = queryMethod(PersonRepository.class, "metaWithMaxScan");
|
||||
|
||||
MongoQueryMethod method = queryMethod("metaWithMaxScan");
|
||||
assertThat(method.hasQueryMetaAttributes(), is(true));
|
||||
assertThat(method.getQueryMetaAttributes().getMaxScan(), is(10L));
|
||||
}
|
||||
@@ -169,8 +161,7 @@ public class MongoQueryMethodUnitTests {
|
||||
@Test
|
||||
public void createsMongoQueryMethodWithCommentCorrectly() throws Exception {
|
||||
|
||||
MongoQueryMethod method = queryMethod(PersonRepository.class, "metaWithComment");
|
||||
|
||||
MongoQueryMethod method = queryMethod("metaWithComment");
|
||||
assertThat(method.hasQueryMetaAttributes(), is(true));
|
||||
assertThat(method.getQueryMetaAttributes().getComment(), is("foo bar"));
|
||||
}
|
||||
@@ -181,8 +172,7 @@ public class MongoQueryMethodUnitTests {
|
||||
@Test
|
||||
public void createsMongoQueryMethodWithSnapshotCorrectly() throws Exception {
|
||||
|
||||
MongoQueryMethod method = queryMethod(PersonRepository.class, "metaWithSnapshotUsage");
|
||||
|
||||
MongoQueryMethod method = queryMethod("metaWithSnapshotUsage");
|
||||
assertThat(method.hasQueryMetaAttributes(), is(true));
|
||||
assertThat(method.getQueryMetaAttributes().getSnapshot(), is(true));
|
||||
}
|
||||
@@ -193,16 +183,14 @@ public class MongoQueryMethodUnitTests {
|
||||
@Test
|
||||
public void fallsBackToRepositoryDomainTypeIfMethodDoesNotReturnADomainType() throws Exception {
|
||||
|
||||
MongoQueryMethod method = queryMethod(PersonRepository.class, "deleteByUserName", String.class);
|
||||
MongoQueryMethod method = queryMethod("deleteByUserName", String.class);
|
||||
|
||||
assertThat(method.getEntityInformation().getJavaType(), is(typeCompatibleWith(User.class)));
|
||||
}
|
||||
|
||||
private MongoQueryMethod queryMethod(Class<?> repository, String name, Class<?>... parameters) throws Exception {
|
||||
|
||||
Method method = repository.getMethod(name, parameters);
|
||||
ProjectionFactory factory = new SpelAwareProxyProjectionFactory();
|
||||
return new MongoQueryMethod(method, new DefaultRepositoryMetadata(repository), factory, 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), context);
|
||||
}
|
||||
|
||||
interface PersonRepository extends Repository<User, Long> {
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Matchers;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.data.mongodb.MongoDbFactory;
|
||||
@@ -41,12 +42,9 @@ import org.springframework.data.mongodb.core.query.TextCriteria;
|
||||
import org.springframework.data.mongodb.repository.MongoRepository;
|
||||
import org.springframework.data.mongodb.repository.Person;
|
||||
import org.springframework.data.mongodb.repository.Query;
|
||||
import org.springframework.data.projection.ProjectionFactory;
|
||||
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
|
||||
import org.springframework.data.repository.core.support.DefaultRepositoryMetadata;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
|
||||
import com.mongodb.BasicDBObjectBuilder;
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.util.JSONParseException;
|
||||
|
||||
/**
|
||||
@@ -54,11 +52,11 @@ import com.mongodb.util.JSONParseException;
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Darimont
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class PartTreeMongoQueryUnitTests {
|
||||
|
||||
@Mock RepositoryMetadata metadataMock;
|
||||
@Mock MongoOperations mongoOperationsMock;
|
||||
|
||||
MongoMappingContext mappingContext;
|
||||
@@ -66,8 +64,11 @@ public class PartTreeMongoQueryUnitTests {
|
||||
public @Rule ExpectedException exception = ExpectedException.none();
|
||||
|
||||
@Before
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public void setUp() {
|
||||
|
||||
when(metadataMock.getDomainType()).thenReturn((Class) Person.class);
|
||||
when(metadataMock.getReturnedDomainClass(Matchers.any(Method.class))).thenReturn((Class) Person.class);
|
||||
mappingContext = new MongoMappingContext();
|
||||
DbRefResolver dbRefResolver = new DefaultDbRefResolver(mock(MongoDbFactory.class));
|
||||
MongoConverter converter = new MappingMongoConverter(dbRefResolver, mappingContext);
|
||||
@@ -147,52 +148,7 @@ public class PartTreeMongoQueryUnitTests {
|
||||
deriveQueryFromMethod("findByAge", new Object[] { 1 });
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1345
|
||||
*/
|
||||
@Test
|
||||
public void doesNotDeriveFieldSpecForNormalDomainType() {
|
||||
assertThat(deriveQueryFromMethod("findPersonBy", new Object[0]).getFieldsObject(), is(nullValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1345
|
||||
*/
|
||||
@Test
|
||||
public void restrictsQueryToFieldsRequiredForProjection() {
|
||||
|
||||
DBObject fieldsObject = deriveQueryFromMethod("findPersonProjectedBy", new Object[0]).getFieldsObject();
|
||||
|
||||
assertThat(fieldsObject.get("firstname"), is((Object) 1));
|
||||
assertThat(fieldsObject.get("lastname"), is((Object) 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1345
|
||||
*/
|
||||
@Test
|
||||
public void restrictsQueryToFieldsRequiredForDto() {
|
||||
|
||||
DBObject fieldsObject = deriveQueryFromMethod("findPersonDtoByAge", new Object[] { 42 }).getFieldsObject();
|
||||
|
||||
assertThat(fieldsObject.get("firstname"), is((Object) 1));
|
||||
assertThat(fieldsObject.get("lastname"), is((Object) 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1345
|
||||
*/
|
||||
@Test
|
||||
public void usesDynamicProjection() {
|
||||
|
||||
DBObject fields = deriveQueryFromMethod("findDynamicallyProjectedBy", ExtendedProjection.class).getFieldsObject();
|
||||
|
||||
assertThat(fields.get("firstname"), is((Object) 1));
|
||||
assertThat(fields.get("lastname"), is((Object) 1));
|
||||
assertThat(fields.get("age"), is((Object) 1));
|
||||
}
|
||||
|
||||
private org.springframework.data.mongodb.core.query.Query deriveQueryFromMethod(String method, Object... args) {
|
||||
private org.springframework.data.mongodb.core.query.Query deriveQueryFromMethod(String method, Object[] args) {
|
||||
|
||||
Class<?>[] types = new Class<?>[args.length];
|
||||
|
||||
@@ -211,9 +167,7 @@ public class PartTreeMongoQueryUnitTests {
|
||||
try {
|
||||
|
||||
Method method = Repo.class.getMethod(methodName, paramTypes);
|
||||
ProjectionFactory factory = new SpelAwareProxyProjectionFactory();
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, new DefaultRepositoryMetadata(Repo.class), factory,
|
||||
mappingContext);
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadataMock, mappingContext);
|
||||
|
||||
return new PartTreeMongoQuery(queryMethod, mongoOperationsMock);
|
||||
} catch (NoSuchMethodException e) {
|
||||
@@ -241,36 +195,5 @@ public class PartTreeMongoQueryUnitTests {
|
||||
|
||||
@Query(fields = "{ 'firstname }")
|
||||
Person findByAge(Integer age);
|
||||
|
||||
Person findPersonBy();
|
||||
|
||||
PersonProjection findPersonProjectedBy();
|
||||
|
||||
PersonDto findPersonDtoByAge(Integer age);
|
||||
|
||||
<T> T findDynamicallyProjectedBy(Class<T> type);
|
||||
}
|
||||
|
||||
interface PersonProjection {
|
||||
|
||||
String getFirstname();
|
||||
|
||||
String getLastname();
|
||||
}
|
||||
|
||||
interface ExtendedProjection extends PersonProjection {
|
||||
|
||||
int getAge();
|
||||
}
|
||||
|
||||
static class PersonDto {
|
||||
|
||||
public String firstname, lastname;
|
||||
|
||||
public PersonDto(String firstname, String lastname) {
|
||||
|
||||
this.firstname = firstname;
|
||||
this.lastname = lastname;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,12 +43,7 @@ import org.springframework.data.mongodb.core.query.BasicQuery;
|
||||
import org.springframework.data.mongodb.repository.Address;
|
||||
import org.springframework.data.mongodb.repository.Person;
|
||||
import org.springframework.data.mongodb.repository.Query;
|
||||
import org.springframework.data.projection.ProjectionFactory;
|
||||
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.core.support.DefaultRepositoryMetadata;
|
||||
import org.springframework.data.repository.query.DefaultEvaluationContextProvider;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.BasicDBObjectBuilder;
|
||||
@@ -65,9 +60,8 @@ import com.mongodb.DBRef;
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class StringBasedMongoQueryUnitTests {
|
||||
|
||||
SpelExpressionParser PARSER = new SpelExpressionParser();
|
||||
|
||||
@Mock MongoOperations operations;
|
||||
@Mock RepositoryMetadata metadata;
|
||||
@Mock DbRefResolver factory;
|
||||
|
||||
MongoConverter converter;
|
||||
@@ -83,7 +77,9 @@ public class StringBasedMongoQueryUnitTests {
|
||||
@Test
|
||||
public void bindsSimplePropertyCorrectly() throws Exception {
|
||||
|
||||
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByLastname", String.class);
|
||||
Method method = SampleRepository.class.getMethod("findByLastname", String.class);
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, converter.getMappingContext());
|
||||
StringBasedMongoQuery mongoQuery = new StringBasedMongoQuery(queryMethod, operations);
|
||||
ConvertingParameterAccessor accesor = StubParameterAccessor.getAccessor(converter, "Matthews");
|
||||
|
||||
org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accesor);
|
||||
@@ -216,9 +212,8 @@ public class StringBasedMongoQueryUnitTests {
|
||||
|
||||
org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accessor);
|
||||
|
||||
assertThat(query.getQueryObject(),
|
||||
is(new BasicQuery("{$where: 'return this.date.getUTCMonth() == 3 && this.date.getUTCDay() == 4;'}")
|
||||
.getQueryObject()));
|
||||
assertThat(query.getQueryObject(), is(new BasicQuery(
|
||||
"{$where: 'return this.date.getUTCMonth() == 3 && this.date.getUTCDay() == 4;'}").getQueryObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -297,54 +292,6 @@ public class StringBasedMongoQueryUnitTests {
|
||||
assertThat(query.getQueryObject(), is(new BasicDBObjectBuilder().add("key", "value").get()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-990
|
||||
*/
|
||||
@Test
|
||||
public void shouldSupportExpressionsInCustomQueries() throws Exception {
|
||||
|
||||
ConvertingParameterAccessor accesor = StubParameterAccessor.getAccessor(converter, "Matthews");
|
||||
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByQueryWithExpression", String.class);
|
||||
|
||||
org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accesor);
|
||||
org.springframework.data.mongodb.core.query.Query reference = new BasicQuery("{'lastname' : 'Matthews'}");
|
||||
|
||||
assertThat(query.getQueryObject(), is(reference.getQueryObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1244
|
||||
*/
|
||||
@Test
|
||||
public void shouldSupportExpressionsInCustomQueriesWithNestedObject() throws Exception {
|
||||
|
||||
ConvertingParameterAccessor accesor = StubParameterAccessor.getAccessor(converter, true, "param1", "param2");
|
||||
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByQueryWithExpressionAndNestedObject", boolean.class,
|
||||
String.class);
|
||||
|
||||
org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accesor);
|
||||
org.springframework.data.mongodb.core.query.Query reference = new BasicQuery("{ \"id\" : { \"$exists\" : true}}");
|
||||
|
||||
assertThat(query.getQueryObject(), is(reference.getQueryObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1244
|
||||
*/
|
||||
@Test
|
||||
public void shouldSupportExpressionsInCustomQueriesWithMultipleNestedObjects() throws Exception {
|
||||
|
||||
ConvertingParameterAccessor accesor = StubParameterAccessor.getAccessor(converter, true, "param1", "param2");
|
||||
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByQueryWithExpressionAndMultipleNestedObjects",
|
||||
boolean.class, String.class, String.class);
|
||||
|
||||
org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accesor);
|
||||
org.springframework.data.mongodb.core.query.Query reference = new BasicQuery(
|
||||
"{ \"id\" : { \"$exists\" : true} , \"foo\" : 42 , \"bar\" : { \"$exists\" : false}}");
|
||||
|
||||
assertThat(query.getQueryObject(), is(reference.getQueryObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1290
|
||||
*/
|
||||
@@ -365,13 +312,11 @@ public class StringBasedMongoQueryUnitTests {
|
||||
private StringBasedMongoQuery createQueryForMethod(String name, Class<?>... parameters) throws Exception {
|
||||
|
||||
Method method = SampleRepository.class.getMethod(name, parameters);
|
||||
ProjectionFactory factory = new SpelAwareProxyProjectionFactory();
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, new DefaultRepositoryMetadata(SampleRepository.class),
|
||||
factory, converter.getMappingContext());
|
||||
return new StringBasedMongoQuery(queryMethod, operations, PARSER, DefaultEvaluationContextProvider.INSTANCE);
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, converter.getMappingContext());
|
||||
return new StringBasedMongoQuery(queryMethod, operations);
|
||||
}
|
||||
|
||||
private interface SampleRepository extends Repository<Person, Long> {
|
||||
private interface SampleRepository {
|
||||
|
||||
@Query("{ 'lastname' : ?0 }")
|
||||
Person findByLastname(String lastname);
|
||||
@@ -412,13 +357,5 @@ public class StringBasedMongoQueryUnitTests {
|
||||
@Query("{ ?0 : ?1}")
|
||||
Object methodWithPlaceholderInKeyOfJsonStructure(String keyReplacement, String valueReplacement);
|
||||
|
||||
@Query("{'lastname': ?#{[0]} }")
|
||||
List<Person> findByQueryWithExpression(String param0);
|
||||
|
||||
@Query("{'id':?#{ [0] ? { $exists :true} : [1] }}")
|
||||
List<Person> findByQueryWithExpressionAndNestedObject(boolean param0, String param1);
|
||||
|
||||
@Query("{'id':?#{ [0] ? { $exists :true} : [1] }, 'foo':42, 'bar': ?#{ [0] ? { $exists :false} : [1] }}")
|
||||
List<Person> findByQueryWithExpressionAndMultipleNestedObjects(boolean param0, String param1, String param2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,6 @@ import org.springframework.data.repository.query.ParameterAccessor;
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Christoh Strobl
|
||||
* @author Thomas Darimont
|
||||
*/
|
||||
class StubParameterAccessor implements MongoParameterAccessor {
|
||||
|
||||
@@ -130,21 +129,4 @@ class StubParameterAccessor implements MongoParameterAccessor {
|
||||
public TextCriteria getFullText() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.repository.query.MongoParameterAccessor#getValues()
|
||||
*/
|
||||
@Override
|
||||
public Object[] getValues() {
|
||||
return this.values;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.query.ParameterAccessor#getDynamicProjection()
|
||||
*/
|
||||
@Override
|
||||
public Class<?> getDynamicProjection() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ import org.springframework.data.mongodb.repository.query.MongoEntityInformation;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import com.querydsl.core.types.Predicate;
|
||||
import com.mysema.query.types.Predicate;
|
||||
|
||||
/**
|
||||
* Integration test for {@link QueryDslMongoRepository}.
|
||||
|
||||
@@ -31,6 +31,8 @@ import org.springframework.data.mongodb.repository.QPerson;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import com.mysema.query.mongodb.MongodbQuery;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link QuerydslRepositorySupport}.
|
||||
*
|
||||
@@ -57,8 +59,8 @@ public class QuerydslRepositorySupportTests {
|
||||
|
||||
QPerson p = QPerson.person;
|
||||
QuerydslRepositorySupport support = new QuerydslRepositorySupport(operations) {};
|
||||
SpringDataMongodbQuery<Person> query = support.from(p).where(p.lastname.eq("Matthews"));
|
||||
assertThat(query.fetchOne(), is(person));
|
||||
MongodbQuery<Person> query = support.from(p).where(p.lastname.eq("Matthews"));
|
||||
assertThat(query.uniqueResult(), is(person));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,8 +76,8 @@ public class QuerydslRepositorySupportTests {
|
||||
QPerson p = QPerson.person;
|
||||
QuerydslRepositorySupport support = new QuerydslRepositorySupport(operations) {};
|
||||
|
||||
SpringDataMongodbQuery<Person> query = support.from(p).where(p.skills.any().in("guitarist"));
|
||||
MongodbQuery<Person> query = support.from(p).where(p.skills.any().in("guitarist"));
|
||||
|
||||
assertThat(query.fetchOne(), is(person));
|
||||
assertThat(query.uniqueResult(), is(person));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,10 +37,10 @@ import org.springframework.data.mongodb.repository.QPerson;
|
||||
import com.mongodb.BasicDBList;
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DBObject;
|
||||
import com.querydsl.core.types.dsl.BooleanOperation;
|
||||
import com.querydsl.core.types.dsl.PathBuilder;
|
||||
import com.querydsl.core.types.dsl.SimplePath;
|
||||
import com.querydsl.core.types.dsl.StringPath;
|
||||
import com.mysema.query.types.expr.BooleanOperation;
|
||||
import com.mysema.query.types.path.PathBuilder;
|
||||
import com.mysema.query.types.path.SimplePath;
|
||||
import com.mysema.query.types.path.StringPath;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link SpringDataMongodbSerializer}.
|
||||
@@ -73,7 +73,6 @@ public class SpringDataMongodbSerializerUnitTests {
|
||||
|
||||
@Test
|
||||
public void buildsNestedKeyCorrectly() {
|
||||
|
||||
StringPath path = QPerson.person.address.street;
|
||||
assertThat(serializer.getKeyForPath(path, path.getMetadata()), is("street"));
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user