Compare commits
20 Commits
3.2.4
...
1.1.2.RELE
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
43d9f2f948 | ||
|
|
fbb281959b | ||
|
|
c9ff78d17b | ||
|
|
b6f5614573 | ||
|
|
3c43a43206 | ||
|
|
b2f82bb5bf | ||
|
|
38ccc59137 | ||
|
|
cfa3e467d1 | ||
|
|
138a4942e9 | ||
|
|
a110197b15 | ||
|
|
0745fe1e25 | ||
|
|
e16d6f4529 | ||
|
|
fa1cc5011b | ||
|
|
90d146235c | ||
|
|
23e1ebc000 | ||
|
|
8850c2caf5 | ||
|
|
49d874d984 | ||
|
|
6fc1b7c1f0 | ||
|
|
eb7c0fe1dd | ||
|
|
55dc16d8fa |
2
pom.xml
2
pom.xml
@@ -6,7 +6,7 @@
|
||||
<name>Spring Data MongoDB Distribution</name>
|
||||
<description>Spring Data project for MongoDB</description>
|
||||
<url>http://www.springsource.org/spring-data/mongodb</url>
|
||||
<version>1.2.0.BUILD-SNAPSHOT</version>
|
||||
<version>1.1.2.RELEASE</version>
|
||||
<packaging>pom</packaging>
|
||||
<modules>
|
||||
<module>spring-data-mongodb</module>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>1.2.0.BUILD-SNAPSHOT</version>
|
||||
<version>1.1.2.RELEASE</version>
|
||||
<relativePath>../spring-data-mongodb-parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>spring-data-mongodb-cross-store</artifactId>
|
||||
@@ -42,7 +42,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb</artifactId>
|
||||
<version>1.2.0.BUILD-SNAPSHOT</version>
|
||||
<version>1.1.2.RELEASE</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
log4j.rootCategory=INFO, stdout
|
||||
|
||||
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %40.40c:%4L - %m%n
|
||||
|
||||
log4j.category.org.springframework=INFO
|
||||
log4j.category.org.springframework.data=TRACE
|
||||
|
||||
log4j.category.org.hibernate.SQL=DEBUG
|
||||
# for debugging datasource initialization
|
||||
# log4j.category.test.jdbc=DEBUG
|
||||
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
|
||||
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d %5p %40.40c:%4L - %m%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!--
|
||||
<logger name="org.springframework" level="debug" />
|
||||
-->
|
||||
|
||||
<root level="error">
|
||||
<appender-ref ref="console" />
|
||||
</root>
|
||||
|
||||
</configuration>
|
||||
@@ -4,12 +4,16 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>1.2.0.BUILD-SNAPSHOT</version>
|
||||
<version>1.1.2.RELEASE</version>
|
||||
<relativePath>../spring-data-mongodb-parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>spring-data-mongodb-log4j</artifactId>
|
||||
<name>Spring Data MongoDB Log4J Appender</name>
|
||||
|
||||
<properties>
|
||||
<log4j.version>1.2.16</log4j.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- MongoDB -->
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<name>Spring Data MongoDB Parent</name>
|
||||
<description>Spring Data project for MongoDB</description>
|
||||
<url>http://www.springsource.org/spring-data/mongodb</url>
|
||||
<version>1.2.0.BUILD-SNAPSHOT</version>
|
||||
<version>1.1.2.RELEASE</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<developers>
|
||||
@@ -84,15 +84,15 @@
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<!-- versions for commonly-used dependencies -->
|
||||
<mongo.version>2.9.1</mongo.version>
|
||||
<mongo.version>2.9.3</mongo.version>
|
||||
<junit.version>4.10</junit.version>
|
||||
<log4j.version>1.2.16</log4j.version>
|
||||
<logback.version>1.0.6</logback.version>
|
||||
<org.mockito.version>1.9.0</org.mockito.version>
|
||||
<org.slf4j.version>1.6.1</org.slf4j.version>
|
||||
<org.codehaus.jackson.version>1.6.1</org.codehaus.jackson.version>
|
||||
<org.springframework.version.30>3.0.7.RELEASE</org.springframework.version.30>
|
||||
<org.springframework.version.range>3.1.2.RELEASE</org.springframework.version.range>
|
||||
<data.commons.version>1.4.0.RELEASE</data.commons.version>
|
||||
<data.commons.version>1.4.1.RELEASE</data.commons.version>
|
||||
<aspectj.version>1.6.11.RELEASE</aspectj.version>
|
||||
<bundlor.failOnWarnings>true</bundlor.failOnWarnings>
|
||||
</properties>
|
||||
@@ -163,14 +163,14 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
<artifactId>jul-to-slf4j</artifactId>
|
||||
<version>${org.slf4j.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>log4j</groupId>
|
||||
<artifactId>log4j</artifactId>
|
||||
<version>${log4j.version}</version>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>${logback.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -265,6 +265,9 @@
|
||||
<exclude>**/PerformanceTests.java</exclude>
|
||||
</excludes>
|
||||
<junitArtifactName>junit:junit-dep</junitArtifactName>
|
||||
<systemPropertyVariables>
|
||||
<java.util.logging.config.file>src/test/resources/logging.properties</java.util.logging.config.file>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
@@ -326,8 +329,8 @@
|
||||
</pluginRepositories>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-libs-release</id>
|
||||
<url>http://repo.springsource.org/libs-release</url>
|
||||
<id>spring-libs-snapshot</id>
|
||||
<url>http://repo.springsource.org/libs-snapshot</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<reporting>
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>1.2.0.BUILD-SNAPSHOT</version>
|
||||
<version>1.1.2.RELEASE</version>
|
||||
<relativePath>../spring-data-mongodb-parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>spring-data-mongodb</artifactId>
|
||||
<name>Spring Data MongoDB</name>
|
||||
|
||||
<properties>
|
||||
<querydsl.version>2.8.0</querydsl.version>
|
||||
<querydsl.version>2.8.2</querydsl.version>
|
||||
<cdi.version>1.0</cdi.version>
|
||||
<validation.version>1.0.0.GA</validation.version>
|
||||
<webbeans.version>1.1.3</webbeans.version>
|
||||
@@ -64,12 +64,6 @@
|
||||
<groupId>org.mongodb</groupId>
|
||||
<artifactId>mongo-java-driver</artifactId>
|
||||
<version>${mongo.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>javax.persistence</groupId>
|
||||
<artifactId>persistence-api</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
@@ -26,4 +26,6 @@ public abstract class BeanNames {
|
||||
static final String MONGO = "mongo";
|
||||
static final String DB_FACTORY = "mongoDbFactory";
|
||||
static final String VALIDATING_EVENT_LISTENER = "validatingMongoEventListener";
|
||||
static final String IS_NEW_STRATEGY_FACTORY = "isNewStrategyFactory";
|
||||
static final String DEFAULT_CONVERTER_BEAN_NAME = "mappingConverter";
|
||||
}
|
||||
|
||||
@@ -24,12 +24,12 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.BeanMetadataElement;
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
@@ -38,6 +38,7 @@ import org.springframework.beans.factory.support.ManagedList;
|
||||
import org.springframework.beans.factory.support.ManagedSet;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
@@ -68,25 +69,26 @@ import org.w3c.dom.Element;
|
||||
* @author Oliver Gierke
|
||||
* @author Maciej Walkowiak
|
||||
*/
|
||||
public class MappingMongoConverterParser extends AbstractBeanDefinitionParser {
|
||||
public class MappingMongoConverterParser implements BeanDefinitionParser {
|
||||
|
||||
private static final String BASE_PACKAGE = "base-package";
|
||||
private static final boolean jsr303Present = ClassUtils.isPresent("javax.validation.Validator",
|
||||
MappingMongoConverterParser.class.getClassLoader());
|
||||
|
||||
@Override
|
||||
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext)
|
||||
throws BeanDefinitionStoreException {
|
||||
String id = super.resolveId(element, definition, parserContext);
|
||||
return StringUtils.hasText(id) ? id : "mappingConverter";
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.xml.BeanDefinitionParser#parse(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext)
|
||||
*/
|
||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
|
||||
@Override
|
||||
protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
|
||||
BeanDefinitionRegistry registry = parserContext.getRegistry();
|
||||
|
||||
String id = element.getAttribute(AbstractBeanDefinitionParser.ID_ATTRIBUTE);
|
||||
id = StringUtils.hasText(id) ? id : "mappingConverter";
|
||||
|
||||
parserContext.pushContainingComponent(new CompositeComponentDefinition("Mapping Mongo Converter", element));
|
||||
|
||||
BeanDefinition conversionsDefinition = getCustomConversions(element, parserContext);
|
||||
String ctxRef = potentiallyCreateMappingContext(element, parserContext, conversionsDefinition);
|
||||
String ctxRef = potentiallyCreateMappingContext(element, parserContext, conversionsDefinition, id);
|
||||
|
||||
// Need a reference to a Mongo instance
|
||||
String dbFactoryRef = element.getAttribute("db-factory-ref");
|
||||
@@ -111,18 +113,23 @@ public class MappingMongoConverterParser extends AbstractBeanDefinitionParser {
|
||||
}
|
||||
BeanDefinitionBuilder indexHelperBuilder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(MongoPersistentEntityIndexCreator.class);
|
||||
indexHelperBuilder.addConstructorArgValue(new RuntimeBeanReference(ctxRef));
|
||||
indexHelperBuilder.addConstructorArgValue(new RuntimeBeanReference(dbFactoryRef));
|
||||
registry.registerBeanDefinition(INDEX_HELPER, indexHelperBuilder.getBeanDefinition());
|
||||
indexHelperBuilder.addConstructorArgReference(ctxRef);
|
||||
indexHelperBuilder.addConstructorArgReference(dbFactoryRef);
|
||||
|
||||
parserContext.registerBeanComponent(new BeanComponentDefinition(indexHelperBuilder.getBeanDefinition(),
|
||||
INDEX_HELPER));
|
||||
}
|
||||
|
||||
BeanDefinition validatingMongoEventListener = potentiallyCreateValidatingMongoEventListener(element, parserContext);
|
||||
|
||||
if (validatingMongoEventListener != null) {
|
||||
registry.registerBeanDefinition(VALIDATING_EVENT_LISTENER, validatingMongoEventListener);
|
||||
parserContext.registerBeanComponent(new BeanComponentDefinition(validatingMongoEventListener,
|
||||
VALIDATING_EVENT_LISTENER));
|
||||
}
|
||||
|
||||
return converterBuilder.getBeanDefinition();
|
||||
parserContext.registerBeanComponent(new BeanComponentDefinition(converterBuilder.getBeanDefinition(), id));
|
||||
parserContext.popAndRegisterContainingComponent();
|
||||
return null;
|
||||
}
|
||||
|
||||
private BeanDefinition potentiallyCreateValidatingMongoEventListener(Element element, ParserContext parserContext) {
|
||||
@@ -136,7 +143,6 @@ public class MappingMongoConverterParser extends AbstractBeanDefinitionParser {
|
||||
RuntimeBeanReference validator = getValidator(builder, parserContext);
|
||||
|
||||
if (validator != null) {
|
||||
|
||||
builder.getRawBeanDefinition().setBeanClass(ValidatingMongoEventListener.class);
|
||||
builder.addConstructorArgValue(validator);
|
||||
|
||||
@@ -158,13 +164,13 @@ public class MappingMongoConverterParser extends AbstractBeanDefinitionParser {
|
||||
validatorDef.setSource(source);
|
||||
validatorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
String validatorName = parserContext.getReaderContext().registerWithGeneratedName(validatorDef);
|
||||
parserContext.registerComponent(new BeanComponentDefinition(validatorDef, validatorName));
|
||||
parserContext.registerBeanComponent(new BeanComponentDefinition(validatorDef, validatorName));
|
||||
|
||||
return new RuntimeBeanReference(validatorName);
|
||||
}
|
||||
|
||||
private String potentiallyCreateMappingContext(Element element, ParserContext parserContext,
|
||||
BeanDefinition conversionsDefinition) {
|
||||
static String potentiallyCreateMappingContext(Element element, ParserContext parserContext,
|
||||
BeanDefinition conversionsDefinition, String converterId) {
|
||||
|
||||
String ctxRef = element.getAttribute("mapping-context-ref");
|
||||
|
||||
@@ -191,11 +197,9 @@ public class MappingMongoConverterParser extends AbstractBeanDefinitionParser {
|
||||
mappingContextBuilder.addPropertyValue("simpleTypeHolder", simpleTypesDefinition);
|
||||
}
|
||||
|
||||
parserContext.getRegistry().registerBeanDefinition(MAPPING_CONTEXT, mappingContextBuilder.getBeanDefinition());
|
||||
ctxRef = MAPPING_CONTEXT;
|
||||
ctxRef = converterId + "." + MAPPING_CONTEXT;
|
||||
|
||||
parserContext.registerBeanComponent(componentDefinitionBuilder.getComponent(mappingContextBuilder, ctxRef));
|
||||
|
||||
return ctxRef;
|
||||
}
|
||||
|
||||
@@ -233,7 +237,7 @@ public class MappingMongoConverterParser extends AbstractBeanDefinitionParser {
|
||||
AbstractBeanDefinition conversionsBean = conversionsBuilder.getBeanDefinition();
|
||||
conversionsBean.setSource(parserContext.extractSource(element));
|
||||
|
||||
parserContext.getRegistry().registerBeanDefinition("customConversions", conversionsBean);
|
||||
parserContext.registerBeanComponent(new BeanComponentDefinition(conversionsBean, "customConversions"));
|
||||
|
||||
return conversionsBean;
|
||||
}
|
||||
@@ -241,7 +245,7 @@ public class MappingMongoConverterParser extends AbstractBeanDefinitionParser {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Set<String> getInititalEntityClasses(Element element, BeanDefinitionBuilder builder) {
|
||||
public static Set<String> getInititalEntityClasses(Element element, BeanDefinitionBuilder builder) {
|
||||
|
||||
String basePackage = element.getAttribute(BASE_PACKAGE);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -13,59 +13,53 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.mongodb.core;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.WriteConcern;
|
||||
|
||||
/**
|
||||
* Represents an action taken against the collection. Used by {@link WriteConcernResolver} to determine a custom
|
||||
* WriteConcern based on this information.
|
||||
*
|
||||
* Properties that will always be not-null are collectionName and defaultWriteConcern. The EntityClass is null only for
|
||||
* the MongoActionOperaton.INSERT_LIST.
|
||||
*
|
||||
* {@link WriteConcern} based on this information.
|
||||
* <ul>
|
||||
* <li>INSERT, SAVE have null query</li>
|
||||
* <li>REMOVE has null document</li>
|
||||
* <li>INSERT_LIST has null entityClass, document, and query</li>
|
||||
* <li>INSERT_LIST has null entityType, document, and query</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Mark Pollack
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class MongoAction {
|
||||
|
||||
private String collectionName;
|
||||
|
||||
private WriteConcern defaultWriteConcern;
|
||||
|
||||
private Class<?> entityClass;
|
||||
|
||||
private MongoActionOperation mongoActionOperation;
|
||||
|
||||
private DBObject query;
|
||||
|
||||
private DBObject document;
|
||||
private final String collectionName;
|
||||
private final WriteConcern defaultWriteConcern;
|
||||
private final Class<?> entityType;
|
||||
private final MongoActionOperation mongoActionOperation;
|
||||
private final DBObject query;
|
||||
private final DBObject document;
|
||||
|
||||
/**
|
||||
* Create an instance of a MongoAction
|
||||
* Create an instance of a {@link MongoAction}.
|
||||
*
|
||||
* @param defaultWriteConcern the default write concern
|
||||
* @param defaultWriteConcern the default write concern.
|
||||
* @param mongoActionOperation action being taken against the collection
|
||||
* @param collectionName the collection name
|
||||
* @param entityClass the POJO that is being operated against
|
||||
* @param collectionName the collection name, must not be {@literal null} or empty.
|
||||
* @param entityType the POJO that is being operated against
|
||||
* @param document the converted DBObject from the POJO or Spring Update object
|
||||
* @param query the converted DBOjbect from the Spring Query object
|
||||
*/
|
||||
public MongoAction(WriteConcern defaultWriteConcern, MongoActionOperation mongoActionOperation,
|
||||
String collectionName, Class<?> entityClass, DBObject document, DBObject query) {
|
||||
super();
|
||||
String collectionName, Class<?> entityType, DBObject document, DBObject query) {
|
||||
|
||||
Assert.hasText(collectionName, "Collection name must not be null or empty!");
|
||||
|
||||
this.defaultWriteConcern = defaultWriteConcern;
|
||||
this.mongoActionOperation = mongoActionOperation;
|
||||
this.collectionName = collectionName;
|
||||
this.entityClass = entityClass;
|
||||
this.entityType = entityType;
|
||||
this.query = query;
|
||||
this.document = document;
|
||||
}
|
||||
@@ -78,8 +72,16 @@ public class MongoAction {
|
||||
return defaultWriteConcern;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #getEntityType()} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public Class<?> getEntityClass() {
|
||||
return entityClass;
|
||||
return entityType;
|
||||
}
|
||||
|
||||
public Class<?> getEntityType() {
|
||||
return entityType;
|
||||
}
|
||||
|
||||
public MongoActionOperation getMongoActionOperation() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,8 +20,8 @@ package org.springframework.data.mongodb.core;
|
||||
* for a given mutating operation
|
||||
*
|
||||
* @author Mark Pollack
|
||||
* @author Oliver Gierke
|
||||
* @see MongoAction
|
||||
*
|
||||
*/
|
||||
public enum MongoActionOperation {
|
||||
|
||||
|
||||
@@ -104,15 +104,16 @@ public abstract class MongoDbUtils {
|
||||
DB db = mongo.getDB(databaseName);
|
||||
boolean credentialsGiven = credentials.hasUsername() && credentials.hasPassword();
|
||||
|
||||
if (credentialsGiven && !db.isAuthenticated()) {
|
||||
synchronized (db) {
|
||||
|
||||
String username = credentials.getUsername();
|
||||
String password = credentials.hasPassword() ? credentials.getPassword() : null;
|
||||
if (credentialsGiven && !db.isAuthenticated()) {
|
||||
|
||||
String username = credentials.getUsername();
|
||||
String password = credentials.hasPassword() ? credentials.getPassword() : null;
|
||||
|
||||
synchronized (db) {
|
||||
if (!db.authenticate(username, password == null ? null : password.toCharArray())) {
|
||||
throw new CannotGetMongoDbConnectionException("Failed to authenticate to database [" + databaseName
|
||||
+ "], username = [" + username + "], password = [" + password + "]", databaseName, credentials);
|
||||
+ "], username = [" + username + "], password = [ -not-shown- ]", databaseName, credentials);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2011 the original author or authors.
|
||||
* Copyright 2010-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,12 +15,6 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core;
|
||||
|
||||
import com.mongodb.MongoException;
|
||||
import com.mongodb.MongoException.CursorNotFound;
|
||||
import com.mongodb.MongoException.DuplicateKey;
|
||||
import com.mongodb.MongoException.Network;
|
||||
import com.mongodb.MongoInternalException;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
@@ -29,21 +23,26 @@ import org.springframework.dao.InvalidDataAccessResourceUsageException;
|
||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||
import org.springframework.data.mongodb.UncategorizedMongoDbException;
|
||||
|
||||
import com.mongodb.MongoException;
|
||||
import com.mongodb.MongoException.CursorNotFound;
|
||||
import com.mongodb.MongoException.DuplicateKey;
|
||||
import com.mongodb.MongoException.Network;
|
||||
import com.mongodb.MongoInternalException;
|
||||
|
||||
/**
|
||||
* Simple {@link PersistenceExceptionTranslator} for Mongo. Convert the given runtime exception to an appropriate
|
||||
* exception from the {@code org.springframework.dao} hierarchy. Return {@literal null} if no translation is
|
||||
* appropriate: any other exception may have resulted from user code, and should not be translated.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Michal Vich
|
||||
*/
|
||||
public class MongoExceptionTranslator implements PersistenceExceptionTranslator {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.dao.support.PersistenceExceptionTranslator#
|
||||
* translateExceptionIfPossible(java.lang.RuntimeException)
|
||||
*/
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.dao.support.PersistenceExceptionTranslator#translateExceptionIfPossible(java.lang.RuntimeException)
|
||||
*/
|
||||
public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
|
||||
|
||||
// Check for well-known MongoException subclasses.
|
||||
@@ -52,14 +51,23 @@ public class MongoExceptionTranslator implements PersistenceExceptionTranslator
|
||||
if (ex instanceof DuplicateKey) {
|
||||
return new DuplicateKeyException(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
if (ex instanceof Network) {
|
||||
return new DataAccessResourceFailureException(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
if (ex instanceof CursorNotFound) {
|
||||
return new DataAccessResourceFailureException(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
if (ex instanceof MongoInternalException) {
|
||||
return new InvalidDataAccessResourceUsageException(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
if (ex instanceof MongoException) {
|
||||
|
||||
int code = ((MongoException) ex).getCode();
|
||||
|
||||
if (code == 11000 || code == 11001) {
|
||||
throw new DuplicateKeyException(ex.getMessage(), ex);
|
||||
} else if (code == 12000 || code == 13440) {
|
||||
@@ -69,9 +77,6 @@ public class MongoExceptionTranslator implements PersistenceExceptionTranslator
|
||||
}
|
||||
return new UncategorizedMongoDbException(ex.getMessage(), ex);
|
||||
}
|
||||
if (ex instanceof MongoInternalException) {
|
||||
return new InvalidDataAccessResourceUsageException(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
// If we get here, we have an exception that resulted from user code,
|
||||
// rather than the persistence provider, so we return null to indicate
|
||||
|
||||
@@ -116,7 +116,7 @@ import com.mongodb.util.JSONParseException;
|
||||
public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(MongoTemplate.class);
|
||||
private static final String ID = "_id";
|
||||
private static final String ID_FIELD = "_id";
|
||||
private static final WriteResultChecking DEFAULT_WRITE_RESULT_CHECKING = WriteResultChecking.NONE;
|
||||
private static final Collection<String> ITERABLE_CLASSES;
|
||||
|
||||
@@ -130,32 +130,16 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
ITERABLE_CLASSES = Collections.unmodifiableCollection(iterableClasses);
|
||||
}
|
||||
|
||||
/*
|
||||
* WriteConcern to be used for write operations if it has been specified.
|
||||
* Otherwise we should not use a WriteConcern defaulting to the one set for
|
||||
* the DB or Collection.
|
||||
*/
|
||||
private WriteConcern writeConcern = null;
|
||||
|
||||
private WriteConcernResolver writeConcernResolver = new DefaultWriteConcernResolver();
|
||||
|
||||
/*
|
||||
* WriteResultChecking to be used for write operations if it has been
|
||||
* specified. Otherwise we should not do any checking.
|
||||
*/
|
||||
private WriteResultChecking writeResultChecking = WriteResultChecking.NONE;
|
||||
|
||||
/**
|
||||
* Set the ReadPreference when operating on a collection. See {@link #prepareCollection(DBCollection)}
|
||||
*/
|
||||
private ReadPreference readPreference = null;
|
||||
|
||||
private final MongoConverter mongoConverter;
|
||||
private final MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
|
||||
private final MongoDbFactory mongoDbFactory;
|
||||
private final MongoExceptionTranslator exceptionTranslator = new MongoExceptionTranslator();
|
||||
private final QueryMapper mapper;
|
||||
|
||||
private WriteConcern writeConcern;
|
||||
private WriteConcernResolver writeConcernResolver = DefaultWriteConcernResolver.INSTANCE;
|
||||
private WriteResultChecking writeResultChecking = WriteResultChecking.NONE;
|
||||
private ReadPreference readPreference;
|
||||
private ApplicationEventPublisher eventPublisher;
|
||||
private ResourceLoader resourceLoader;
|
||||
private MongoPersistentEntityIndexCreator indexCreator;
|
||||
@@ -163,8 +147,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
/**
|
||||
* Constructor used for a basic template configuration
|
||||
*
|
||||
* @param mongo
|
||||
* @param databaseName
|
||||
* @param mongo must not be {@literal null}.
|
||||
* @param databaseName must not be {@literal null} or empty.
|
||||
*/
|
||||
public MongoTemplate(Mongo mongo, String databaseName) {
|
||||
this(new SimpleMongoDbFactory(mongo, databaseName), null);
|
||||
@@ -174,8 +158,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
* Constructor used for a template configuration with user credentials in the form of
|
||||
* {@link org.springframework.data.authentication.UserCredentials}
|
||||
*
|
||||
* @param mongo
|
||||
* @param databaseName
|
||||
* @param mongo must not be {@literal null}.
|
||||
* @param databaseName must not be {@literal null} or empty.
|
||||
* @param userCredentials
|
||||
*/
|
||||
public MongoTemplate(Mongo mongo, String databaseName, UserCredentials userCredentials) {
|
||||
@@ -183,9 +167,9 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor used for a basic template configuration
|
||||
* Constructor used for a basic template configuration.
|
||||
*
|
||||
* @param mongoDbFactory
|
||||
* @param mongoDbFactory must not be {@literal null}.
|
||||
*/
|
||||
public MongoTemplate(MongoDbFactory mongoDbFactory) {
|
||||
this(mongoDbFactory, null);
|
||||
@@ -194,7 +178,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
/**
|
||||
* Constructor used for a basic template configuration.
|
||||
*
|
||||
* @param mongoDbFactory
|
||||
* @param mongoDbFactory must not be {@literal null}.
|
||||
* @param mongoConverter
|
||||
*/
|
||||
public MongoTemplate(MongoDbFactory mongoDbFactory, MongoConverter mongoConverter) {
|
||||
@@ -228,7 +212,9 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the {@link WriteConcern} to be used with the template.
|
||||
* Configures the {@link WriteConcern} to be used with the template. If none is configured the {@link WriteConcern}
|
||||
* configured on the {@link MongoDbFactory} will apply. If you configured a {@link Mongo} instance no
|
||||
* {@link WriteConcern} will be used.
|
||||
*
|
||||
* @param writeConcern
|
||||
*/
|
||||
@@ -276,7 +262,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
* can be found we manually add the internally created one as {@link ApplicationListener} to make sure indexes get
|
||||
* created appropriately for entity types persisted through this {@link MongoTemplate} instance.
|
||||
*
|
||||
* @param context
|
||||
* @param context must not be {@literal null}.
|
||||
*/
|
||||
private void prepareIndexCreator(ApplicationContext context) {
|
||||
|
||||
@@ -501,8 +487,13 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
|
||||
public <T> List<T> find(final Query query, Class<T> entityClass, String collectionName) {
|
||||
CursorPreparer cursorPreparer = query == null ? null : new QueryCursorPreparer(query);
|
||||
return doFind(collectionName, query.getQueryObject(), query.getFieldsObject(), entityClass, cursorPreparer);
|
||||
|
||||
if (query == null) {
|
||||
return findAll(entityClass, collectionName);
|
||||
}
|
||||
|
||||
return doFind(collectionName, query.getQueryObject(), query.getFieldsObject(), entityClass,
|
||||
new QueryCursorPreparer(query));
|
||||
}
|
||||
|
||||
public <T> T findById(Object id, Class<T> entityClass) {
|
||||
@@ -512,7 +503,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
public <T> T findById(Object id, Class<T> entityClass, String collectionName) {
|
||||
MongoPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(entityClass);
|
||||
MongoPersistentProperty idProperty = persistentEntity == null ? null : persistentEntity.getIdProperty();
|
||||
String idKey = idProperty == null ? ID : idProperty.getName();
|
||||
String idKey = idProperty == null ? ID_FIELD : idProperty.getName();
|
||||
return doFindOne(collectionName, new BasicDBObject(idKey, id), null, entityClass);
|
||||
}
|
||||
|
||||
@@ -657,6 +648,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
assertUpdateableIdIfNotSet(objectToSave);
|
||||
|
||||
initializeVersionProperty(objectToSave);
|
||||
|
||||
BasicDBObject dbDoc = new BasicDBObject();
|
||||
|
||||
maybeEmitEvent(new BeforeConvertEvent<T>(objectToSave));
|
||||
@@ -669,6 +662,16 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
maybeEmitEvent(new AfterSaveEvent<T>(objectToSave, dbDoc));
|
||||
}
|
||||
|
||||
private void initializeVersionProperty(Object entity) {
|
||||
|
||||
MongoPersistentEntity<?> mongoPersistentEntity = getPersistentEntity(entity.getClass());
|
||||
|
||||
if (mongoPersistentEntity == null || mongoPersistentEntity.hasVersionProperty()) {
|
||||
BeanWrapper<PersistentEntity<Object, ?>, Object> wrapper = BeanWrapper.create(entity, null);
|
||||
wrapper.setProperty(mongoPersistentEntity.getVersionProperty(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
public void insert(Collection<? extends Object> batchToSave, Class<?> entityClass) {
|
||||
doInsertBatch(determineCollectionName(entityClass), batchToSave, this.mongoConverter);
|
||||
}
|
||||
@@ -713,6 +716,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
List<DBObject> dbObjectList = new ArrayList<DBObject>();
|
||||
for (T o : batchToSave) {
|
||||
|
||||
initializeVersionProperty(o);
|
||||
BasicDBObject dbDoc = new BasicDBObject();
|
||||
|
||||
maybeEmitEvent(new BeforeConvertEvent<T>(o));
|
||||
@@ -785,7 +790,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
this.mongoConverter.write(objectToSave, dbObject);
|
||||
|
||||
maybeEmitEvent(new BeforeSaveEvent<T>(objectToSave, dbObject));
|
||||
Update update = Update.fromDBObject(dbObject, ID);
|
||||
Update update = Update.fromDBObject(dbObject, ID_FIELD);
|
||||
|
||||
updateFirst(query, update, objectToSave.getClass());
|
||||
maybeEmitEvent(new AfterSaveEvent<T>(objectToSave, dbObject));
|
||||
@@ -820,21 +825,17 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
protected Object insertDBObject(final String collectionName, final DBObject dbDoc, final Class<?> entityClass) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("insert DBObject containing fields: " + dbDoc.keySet() + " in collection: " + collectionName);
|
||||
LOGGER.debug("Inserting DBObject containing fields: " + dbDoc.keySet() + " in collection: " + collectionName);
|
||||
}
|
||||
return execute(collectionName, new CollectionCallback<Object>() {
|
||||
public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||
MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.INSERT, collectionName,
|
||||
entityClass, dbDoc, null);
|
||||
WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction);
|
||||
WriteResult wr;
|
||||
if (writeConcernToUse == null) {
|
||||
wr = collection.insert(dbDoc);
|
||||
} else {
|
||||
wr = collection.insert(dbDoc, writeConcernToUse);
|
||||
}
|
||||
handleAnyWriteResultErrors(wr, dbDoc, "insert");
|
||||
return dbDoc.get(ID);
|
||||
WriteResult writeResult = writeConcernToUse == null ? collection.insert(dbDoc) : collection.insert(dbDoc,
|
||||
writeConcernToUse);
|
||||
handleAnyWriteResultErrors(writeResult, dbDoc, MongoActionOperation.INSERT);
|
||||
return dbDoc.get(ID_FIELD);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -845,27 +846,23 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("insert list of DBObjects containing " + dbDocList.size() + " items");
|
||||
LOGGER.debug("Inserting list of DBObjects containing " + dbDocList.size() + " items");
|
||||
}
|
||||
execute(collectionName, new CollectionCallback<Void>() {
|
||||
public Void doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||
MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.INSERT_LIST, collectionName, null,
|
||||
null, null);
|
||||
WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction);
|
||||
WriteResult wr;
|
||||
if (writeConcernToUse == null) {
|
||||
wr = collection.insert(dbDocList);
|
||||
} else {
|
||||
wr = collection.insert(dbDocList.toArray((DBObject[]) new BasicDBObject[dbDocList.size()]), writeConcernToUse);
|
||||
}
|
||||
handleAnyWriteResultErrors(wr, null, "insert_list");
|
||||
WriteResult writeResult = writeConcernToUse == null ? collection.insert(dbDocList) : collection.insert(
|
||||
dbDocList.toArray((DBObject[]) new BasicDBObject[dbDocList.size()]), writeConcernToUse);
|
||||
handleAnyWriteResultErrors(writeResult, null, MongoActionOperation.INSERT_LIST);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
List<ObjectId> ids = new ArrayList<ObjectId>();
|
||||
for (DBObject dbo : dbDocList) {
|
||||
Object id = dbo.get(ID);
|
||||
Object id = dbo.get(ID_FIELD);
|
||||
if (id instanceof ObjectId) {
|
||||
ids.add((ObjectId) id);
|
||||
} else {
|
||||
@@ -878,21 +875,17 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
protected Object saveDBObject(final String collectionName, final DBObject dbDoc, final Class<?> entityClass) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("save DBObject containing fields: " + dbDoc.keySet());
|
||||
LOGGER.debug("Saving DBObject containing fields: " + dbDoc.keySet());
|
||||
}
|
||||
return execute(collectionName, new CollectionCallback<Object>() {
|
||||
public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||
MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.SAVE, collectionName, entityClass,
|
||||
dbDoc, null);
|
||||
WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction);
|
||||
WriteResult wr;
|
||||
if (writeConcernToUse == null) {
|
||||
wr = collection.save(dbDoc);
|
||||
} else {
|
||||
wr = collection.save(dbDoc, writeConcernToUse);
|
||||
}
|
||||
handleAnyWriteResultErrors(wr, dbDoc, "save");
|
||||
return dbDoc.get(ID);
|
||||
WriteResult writeResult = writeConcernToUse == null ? collection.save(dbDoc) : collection.save(dbDoc,
|
||||
writeConcernToUse);
|
||||
handleAnyWriteResultErrors(writeResult, dbDoc, MongoActionOperation.SAVE);
|
||||
return dbDoc.get(ID_FIELD);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -935,29 +928,25 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
entity);
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("calling update using query: " + queryObj + " and update: " + updateObj + " in collection: "
|
||||
LOGGER.debug("Calling update using query: " + queryObj + " and update: " + updateObj + " in collection: "
|
||||
+ collectionName);
|
||||
}
|
||||
|
||||
WriteResult wr;
|
||||
MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.UPDATE, collectionName,
|
||||
entityClass, updateObj, queryObj);
|
||||
WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction);
|
||||
if (writeConcernToUse == null) {
|
||||
wr = collection.update(queryObj, updateObj, upsert, multi);
|
||||
} else {
|
||||
wr = collection.update(queryObj, updateObj, upsert, multi, writeConcernToUse);
|
||||
}
|
||||
WriteResult writeResult = writeConcernToUse == null ? collection.update(queryObj, updateObj, upsert, multi)
|
||||
: collection.update(queryObj, updateObj, upsert, multi, writeConcernToUse);
|
||||
|
||||
if (entity != null && entity.hasVersionProperty() && !multi) {
|
||||
if (wr.getN() == 0) {
|
||||
if (writeResult.getN() == 0) {
|
||||
throw new OptimisticLockingFailureException("Optimistic lock exception on saving entity: "
|
||||
+ updateObj.toMap().toString());
|
||||
}
|
||||
}
|
||||
|
||||
handleAnyWriteResultErrors(wr, queryObj, "update with '" + updateObj + "'");
|
||||
return wr;
|
||||
handleAnyWriteResultErrors(writeResult, queryObj, MongoActionOperation.UPDATE);
|
||||
return writeResult;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1031,27 +1020,30 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
|
||||
protected <T> void doRemove(final String collectionName, final Query query, final Class<T> entityClass) {
|
||||
|
||||
if (query == null) {
|
||||
throw new InvalidDataAccessApiUsageException("Query passed in to remove can't be null");
|
||||
}
|
||||
|
||||
final DBObject queryObject = query.getQueryObject();
|
||||
final MongoPersistentEntity<?> entity = getPersistentEntity(entityClass);
|
||||
|
||||
execute(collectionName, new CollectionCallback<Void>() {
|
||||
public Void doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||
|
||||
DBObject dboq = mapper.getMappedObject(queryObject, entity);
|
||||
WriteResult wr = null;
|
||||
|
||||
MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.REMOVE, collectionName,
|
||||
entityClass, null, queryObject);
|
||||
WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction);
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("remove using query: " + dboq + " in collection: " + collection.getName());
|
||||
LOGGER.debug("Remove using query: {} in collection: {}.", new Object[] { dboq, collection.getName() });
|
||||
}
|
||||
if (writeConcernToUse == null) {
|
||||
wr = collection.remove(dboq);
|
||||
} else {
|
||||
wr = collection.remove(dboq, writeConcernToUse);
|
||||
}
|
||||
handleAnyWriteResultErrors(wr, dboq, "remove");
|
||||
|
||||
WriteResult wr = writeConcernToUse == null ? collection.remove(dboq) : collection.remove(dboq,
|
||||
writeConcernToUse);
|
||||
handleAnyWriteResultErrors(wr, dboq, MongoActionOperation.REMOVE);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
@@ -1108,7 +1100,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
handleCommandError(commandResult, commandObject);
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug(String.format("MapReduce command result = [%s]", serializeToJsonSafely(commandObject)));
|
||||
LOGGER.debug("MapReduce command result = [{}]", serializeToJsonSafely(commandObject));
|
||||
}
|
||||
|
||||
MapReduceOutput mapReduceOutput = new MapReduceOutput(inputCollection, commandObject, commandResult);
|
||||
@@ -1161,14 +1153,14 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
DBObject commandObject = new BasicDBObject("group", dbo);
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug(String.format("Executing Group with DBObject [%s]", serializeToJsonSafely(commandObject)));
|
||||
LOGGER.debug("Executing Group with DBObject [{}]", serializeToJsonSafely(commandObject));
|
||||
}
|
||||
|
||||
CommandResult commandResult = executeCommand(commandObject, getDb().getOptions());
|
||||
handleCommandError(commandResult, commandObject);
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Group command result = [" + commandResult + "]");
|
||||
LOGGER.debug("Group command result = [{}]", commandResult);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -1284,7 +1276,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
DBCollection coll = db.createCollection(collectionName, collectionOptions);
|
||||
// TODO: Emit a collection created event
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Created collection [" + coll.getFullName() + "]");
|
||||
LOGGER.debug("Created collection [{}]", coll.getFullName());
|
||||
}
|
||||
return coll;
|
||||
}
|
||||
@@ -1312,14 +1304,10 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
|
||||
/**
|
||||
* Map the results of an ad-hoc query on the default MongoDB collection to a List of the specified type.
|
||||
* <p/>
|
||||
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
|
||||
* configured otherwise, an instance of SimpleMongoConverter will be used.
|
||||
* <p/>
|
||||
* The query document is specified as a standard DBObject and so is the fields specification.
|
||||
* <p/>
|
||||
* Can be overridden by subclasses.
|
||||
* Map the results of an ad-hoc query on the default MongoDB collection to a List of the specified type. The object is
|
||||
* converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless configured
|
||||
* otherwise, an instance of SimpleMongoConverter will be used. The query document is specified as a standard DBObject
|
||||
* and so is the fields specification. Can be overridden by subclasses.
|
||||
*
|
||||
* @param collectionName name of the collection to retrieve the objects from
|
||||
* @param query the query document that specifies the criteria used to find a record
|
||||
@@ -1350,9 +1338,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
|
||||
/**
|
||||
* Map the results of an ad-hoc query on the default MongoDB collection to a List using the template's converter.
|
||||
* <p/>
|
||||
* The query document is specified as a standard DBObject and so is the fields specification.
|
||||
* Map the results of an ad-hoc query on the default MongoDB collection to a List using the template's converter. The
|
||||
* query document is specified as a standard DBObject and so is the fields specification.
|
||||
*
|
||||
* @param collectionName name of the collection to retrieve the objects from
|
||||
* @param query the query document that specifies the criteria used to find a record
|
||||
@@ -1451,7 +1438,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
if (savedObject instanceof BasicDBObject) {
|
||||
DBObject dbObject = (DBObject) savedObject;
|
||||
dbObject.put(ID, id);
|
||||
dbObject.put(ID_FIELD, id);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1531,19 +1518,32 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
CursorPreparer preparer, DbObjectCallback<T> objectCallback, String collectionName) {
|
||||
|
||||
try {
|
||||
DBCursor cursor = collectionCallback.doInCollection(getAndPrepareCollection(getDb(), collectionName));
|
||||
|
||||
if (preparer != null) {
|
||||
cursor = preparer.prepare(cursor);
|
||||
DBCursor cursor = null;
|
||||
|
||||
try {
|
||||
|
||||
cursor = collectionCallback.doInCollection(getAndPrepareCollection(getDb(), collectionName));
|
||||
|
||||
if (preparer != null) {
|
||||
cursor = preparer.prepare(cursor);
|
||||
}
|
||||
|
||||
List<T> result = new ArrayList<T>();
|
||||
|
||||
while (cursor.hasNext()) {
|
||||
DBObject object = cursor.next();
|
||||
result.add(objectCallback.doWith(object));
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
} finally {
|
||||
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
List<T> result = new ArrayList<T>();
|
||||
|
||||
for (DBObject object : cursor) {
|
||||
result.add(objectCallback.doWith(object));
|
||||
}
|
||||
|
||||
return result;
|
||||
} catch (RuntimeException e) {
|
||||
throw potentiallyConvertRuntimeException(e);
|
||||
}
|
||||
@@ -1553,15 +1553,27 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
DocumentCallbackHandler callbackHandler, String collectionName) {
|
||||
|
||||
try {
|
||||
DBCursor cursor = collectionCallback.doInCollection(getAndPrepareCollection(getDb(), collectionName));
|
||||
|
||||
if (preparer != null) {
|
||||
cursor = preparer.prepare(cursor);
|
||||
DBCursor cursor = null;
|
||||
|
||||
try {
|
||||
cursor = collectionCallback.doInCollection(getAndPrepareCollection(getDb(), collectionName));
|
||||
|
||||
if (preparer != null) {
|
||||
cursor = preparer.prepare(cursor);
|
||||
}
|
||||
|
||||
while (cursor.hasNext()) {
|
||||
DBObject dbobject = cursor.next();
|
||||
callbackHandler.processDocument(dbobject);
|
||||
}
|
||||
|
||||
} finally {
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
for (DBObject dbobject : cursor) {
|
||||
callbackHandler.processDocument(dbobject);
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
throw potentiallyConvertRuntimeException(e);
|
||||
}
|
||||
@@ -1600,37 +1612,45 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks and handles any errors.
|
||||
* <p/>
|
||||
* Current implementation logs errors. Future version may make this configurable to log warning, errors or throw
|
||||
* exception.
|
||||
* Handles {@link WriteResult} errors based on the configured {@link WriteResultChecking}.
|
||||
*
|
||||
* @param writeResult
|
||||
* @param query
|
||||
* @param operation
|
||||
*/
|
||||
protected void handleAnyWriteResultErrors(WriteResult wr, DBObject query, String operation) {
|
||||
protected void handleAnyWriteResultErrors(WriteResult writeResult, DBObject query, MongoActionOperation operation) {
|
||||
|
||||
if (WriteResultChecking.NONE == this.writeResultChecking) {
|
||||
if (writeResultChecking == WriteResultChecking.NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
String error = wr.getError();
|
||||
String error = writeResult.getError();
|
||||
|
||||
if (error != null) {
|
||||
String message;
|
||||
if (operation.equals("insert") || operation.equals("save")) {
|
||||
// assuming the insert operations will begin with insert string
|
||||
if (error == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String message;
|
||||
|
||||
switch (operation) {
|
||||
|
||||
case INSERT:
|
||||
case SAVE:
|
||||
message = String.format("Insert/Save for %s failed: %s", query, error);
|
||||
} else if (operation.equals("insert_list")) {
|
||||
break;
|
||||
case INSERT_LIST:
|
||||
message = String.format("Insert list failed: %s", error);
|
||||
} else {
|
||||
break;
|
||||
default:
|
||||
message = String.format("Execution of %s%s failed: %s", operation,
|
||||
query == null ? "" : "' using '" + query.toString() + "' query", error);
|
||||
}
|
||||
query == null ? "" : " using query " + query.toString(), error);
|
||||
}
|
||||
|
||||
if (WriteResultChecking.EXCEPTION == this.writeResultChecking) {
|
||||
throw new DataIntegrityViolationException(message);
|
||||
} else {
|
||||
LOGGER.error(message);
|
||||
return;
|
||||
}
|
||||
if (writeResultChecking == WriteResultChecking.EXCEPTION) {
|
||||
throw new DataIntegrityViolationException(message);
|
||||
} else {
|
||||
LOGGER.error(message);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1718,7 +1738,6 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
private static class FindCallback implements CollectionCallback<DBCursor> {
|
||||
|
||||
private final DBObject query;
|
||||
|
||||
private final DBObject fields;
|
||||
|
||||
public FindCallback(DBObject query) {
|
||||
@@ -1826,12 +1845,13 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
}
|
||||
|
||||
private class DefaultWriteConcernResolver implements WriteConcernResolver {
|
||||
private enum DefaultWriteConcernResolver implements WriteConcernResolver {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
public WriteConcern resolve(MongoAction action) {
|
||||
return action.getDefaultWriteConcern();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class QueryCursorPreparer implements CursorPreparer {
|
||||
@@ -1895,7 +1915,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
* Creates a new {@link GeoNearResultDbObjectCallback} using the given {@link DbObjectCallback} delegate for
|
||||
* {@link GeoResult} content unmarshalling.
|
||||
*
|
||||
* @param delegate
|
||||
* @param delegate must not be {@literal null}.
|
||||
*/
|
||||
public GeoNearResultDbObjectCallback(DbObjectCallback<T> delegate, Metric metric) {
|
||||
Assert.notNull(delegate);
|
||||
|
||||
@@ -47,7 +47,7 @@ public class SimpleMongoDbFactory implements DisposableBean, MongoDbFactory {
|
||||
* Create an instance of {@link SimpleMongoDbFactory} given the {@link Mongo} instance and database name.
|
||||
*
|
||||
* @param mongo Mongo instance, must not be {@literal null}.
|
||||
* @param databaseName database name, not be {@literal null}.
|
||||
* @param databaseName database name, not be {@literal null} or empty.
|
||||
*/
|
||||
public SimpleMongoDbFactory(Mongo mongo, String databaseName) {
|
||||
this(mongo, databaseName, UserCredentials.NO_CREDENTIALS, false);
|
||||
@@ -57,7 +57,7 @@ public class SimpleMongoDbFactory implements DisposableBean, MongoDbFactory {
|
||||
* Create an instance of SimpleMongoDbFactory given the Mongo instance, database name, and username/password
|
||||
*
|
||||
* @param mongo Mongo instance, must not be {@literal null}.
|
||||
* @param databaseName Database name, must not be {@literal null}.
|
||||
* @param databaseName Database name, must not be {@literal null} or empty.
|
||||
* @param credentials username and password.
|
||||
*/
|
||||
public SimpleMongoDbFactory(Mongo mongo, String databaseName, UserCredentials credentials) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -13,27 +13,25 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.mongodb.core;
|
||||
|
||||
import com.mongodb.WriteConcern;
|
||||
|
||||
/**
|
||||
* A strategy interface to determine the WriteConcern to use for a given MongoDbAction.
|
||||
*
|
||||
* Return the passed in default WriteConcern (a property on MongoAction) if no determination can be made.
|
||||
* A strategy interface to determine the {@link WriteConcern} to use for a given {@link MongoAction}. Return the passed
|
||||
* in default {@link WriteConcern} (a property on {@link MongoAction}) if no determination can be made.
|
||||
*
|
||||
* @author Mark Pollack
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface WriteConcernResolver {
|
||||
|
||||
/**
|
||||
* Resolve the WriteConcern given the MongoAction
|
||||
* Resolve the {@link WriteConcern} given the {@link MongoAction}.
|
||||
*
|
||||
* @param action describes the context of the Mongo action. Contains a default WriteConcern to use if one should not
|
||||
* be resolved.
|
||||
* @return a WriteConcern based on the passed in MongoAction value, maybe null
|
||||
* @param action describes the context of the Mongo action. Contains a default {@link WriteConcern} to use if one
|
||||
* should not be resolved.
|
||||
* @return a {@link WriteConcern} based on the passed in {@link MongoAction} value, maybe {@literal null}.
|
||||
*/
|
||||
WriteConcern resolve(MongoAction action);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,28 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core;
|
||||
|
||||
/**
|
||||
* Enum to represent how strict the check of {@link com.mongodb.WriteResult} shall be. It can either be skipped entirely
|
||||
* (use {@link #NONE}), or errors can be logged ({@link #LOG}) or cause an exception to be thrown {@link #EXCEPTION}.
|
||||
*
|
||||
* @author Thomas Risberg
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public enum WriteResultChecking {
|
||||
|
||||
NONE, LOG, EXCEPTION
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) 2011 by the original author(s).
|
||||
* Copyright 2011-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -13,7 +13,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import java.math.BigInteger;
|
||||
@@ -33,8 +32,8 @@ import org.springframework.data.mongodb.core.convert.MongoConverters.StringToObj
|
||||
* Base class for {@link MongoConverter} implementations. Sets up a {@link GenericConversionService} and populates basic
|
||||
* converters. Allows registering {@link CustomConversions}.
|
||||
*
|
||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||
* @author Oliver Gierke ogierke@vmware.com
|
||||
* @author Jon Brisbin
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public abstract class AbstractMongoConverter implements MongoConverter, InitializingBean {
|
||||
|
||||
@@ -94,6 +93,14 @@ public abstract class AbstractMongoConverter implements MongoConverter, Initiali
|
||||
conversions.registerConvertersIn(conversionService);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.convert.MongoWriter#convertToMongoType(java.lang.Object)
|
||||
*/
|
||||
public Object convertToMongoType(Object obj) {
|
||||
return convertToMongoType(obj, null);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.core.convert.MongoConverter#getConversionService()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2012 by the original author(s).
|
||||
* Copyright 2011-2013 by the original author(s).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -813,8 +813,12 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
return rootList;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.convert.MongoWriter#convertToMongoType(java.lang.Object, org.springframework.data.util.TypeInformation)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object convertToMongoType(Object obj) {
|
||||
public Object convertToMongoType(Object obj, TypeInformation<?> typeInformation) {
|
||||
|
||||
if (obj == null) {
|
||||
return null;
|
||||
@@ -861,7 +865,12 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
|
||||
DBObject newDbo = new BasicDBObject();
|
||||
this.write(obj, newDbo);
|
||||
return removeTypeInfoRecursively(newDbo);
|
||||
|
||||
if (typeInformation == null) {
|
||||
return removeTypeInfoRecursively(newDbo);
|
||||
}
|
||||
|
||||
return !obj.getClass().equals(typeInformation.getType()) ? newDbo : removeTypeInfoRecursively(newDbo);
|
||||
}
|
||||
|
||||
public BasicDBList maybeConvertList(Iterable<?> source) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2012 the original author or authors.
|
||||
* Copyright 2010-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,6 +17,7 @@ package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import org.springframework.data.convert.EntityWriter;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.DBRef;
|
||||
@@ -35,11 +36,21 @@ public interface MongoWriter<T> extends EntityWriter<T, DBObject> {
|
||||
* Converts the given object into one Mongo will be able to store natively. If the given object can already be stored
|
||||
* as is, no conversion will happen.
|
||||
*
|
||||
* @param obj
|
||||
* @param obj can be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
Object convertToMongoType(Object obj);
|
||||
|
||||
/**
|
||||
* Converts the given object into one Mongo will be able to store natively but retains the type information in case
|
||||
* the given {@link TypeInformation} differs from the given object type.
|
||||
*
|
||||
* @param obj can be {@literal null}.
|
||||
* @param typeInformation can be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
Object convertToMongoType(Object obj, TypeInformation<?> typeInformation);
|
||||
|
||||
/**
|
||||
* Creates a {@link DBRef} to refer to the given object.
|
||||
*
|
||||
|
||||
@@ -263,7 +263,7 @@ public class QueryMapper {
|
||||
return result;
|
||||
}
|
||||
|
||||
return source instanceof DBRef ? source : converter.toDBRef(source, property);
|
||||
return source == null || source instanceof DBRef ? source : converter.toDBRef(source, property);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -117,7 +117,7 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
|
||||
|
||||
protected List<?> readCollection(Query query) {
|
||||
|
||||
MongoEntityInformation<?, ?> metadata = method.getEntityInformation();
|
||||
MongoEntityMetadata<?> metadata = method.getEntityInformation();
|
||||
|
||||
String collectionName = metadata.getCollectionName();
|
||||
return operations.find(query, metadata.getJavaType(), collectionName);
|
||||
@@ -175,7 +175,7 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
Object execute(Query query) {
|
||||
|
||||
MongoEntityInformation<?, ?> metadata = method.getEntityInformation();
|
||||
MongoEntityMetadata<?> metadata = method.getEntityInformation();
|
||||
long count = operations.count(query, metadata.getCollectionName());
|
||||
|
||||
List<?> result = operations.find(query.with(pageable), metadata.getJavaType(), metadata.getCollectionName());
|
||||
@@ -198,8 +198,8 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
|
||||
@Override
|
||||
Object execute(Query query) {
|
||||
|
||||
MongoEntityInformation<?, ?> entityInformation = method.getEntityInformation();
|
||||
return operations.findOne(query, entityInformation.getJavaType());
|
||||
MongoEntityMetadata<?> metadata = method.getEntityInformation();
|
||||
return operations.findOne(query, metadata.getJavaType());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,8 +236,8 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
|
||||
*/
|
||||
Object execute(Query query, Query countQuery) {
|
||||
|
||||
MongoEntityInformation<?, ?> information = method.getEntityInformation();
|
||||
long count = operations.count(countQuery, information.getCollectionName());
|
||||
MongoEntityMetadata<?> metadata = method.getEntityInformation();
|
||||
long count = operations.count(countQuery, metadata.getCollectionName());
|
||||
|
||||
return new GeoPage<Object>(doExecuteQuery(query), accessor.getPageable(), count);
|
||||
}
|
||||
@@ -257,9 +257,8 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
|
||||
nearQuery.maxDistance(maxDistance);
|
||||
}
|
||||
|
||||
MongoEntityInformation<?, ?> entityInformation = method.getEntityInformation();
|
||||
return (GeoResults<Object>) operations.geoNear(nearQuery, entityInformation.getJavaType(),
|
||||
entityInformation.getCollectionName());
|
||||
MongoEntityMetadata<?> metadata = method.getEntityInformation();
|
||||
return (GeoResults<Object>) operations.geoNear(nearQuery, metadata.getJavaType(), metadata.getCollectionName());
|
||||
}
|
||||
|
||||
private boolean isListOfGeoResult() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
* Copyright 2011-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -28,6 +28,7 @@ import org.springframework.data.mongodb.core.geo.Distance;
|
||||
import org.springframework.data.mongodb.core.geo.Point;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
import org.springframework.data.repository.query.ParameterAccessor;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
@@ -85,12 +86,12 @@ public class ConvertingParameterAccessor implements MongoParameterAccessor {
|
||||
return delegate.getSort();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.query.ParameterAccessor#getBindableParameter(int)
|
||||
*/
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.query.ParameterAccessor#getBindableValue(int)
|
||||
*/
|
||||
public Object getBindableValue(int index) {
|
||||
|
||||
return getConvertedValue(delegate.getBindableValue(index));
|
||||
return getConvertedValue(delegate.getBindableValue(index), null);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -101,7 +102,8 @@ public class ConvertingParameterAccessor implements MongoParameterAccessor {
|
||||
return delegate.getMaxDistance();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.repository.MongoParameterAccessor#getGeoNearLocation()
|
||||
*/
|
||||
public Point getGeoNearLocation() {
|
||||
@@ -111,11 +113,12 @@ public class ConvertingParameterAccessor implements MongoParameterAccessor {
|
||||
/**
|
||||
* Converts the given value with the underlying {@link MongoWriter}.
|
||||
*
|
||||
* @param value
|
||||
* @param value can be {@literal null}.
|
||||
* @param typeInformation can be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
private Object getConvertedValue(Object value) {
|
||||
return writer.convertToMongoType(value);
|
||||
private Object getConvertedValue(Object value, TypeInformation<?> typeInformation) {
|
||||
return writer.convertToMongoType(value, typeInformation == null ? null : typeInformation.getActualType());
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -186,7 +189,7 @@ public class ConvertingParameterAccessor implements MongoParameterAccessor {
|
||||
}
|
||||
}
|
||||
|
||||
return getConvertedValue(next);
|
||||
return getConvertedValue(next, property.getTypeInformation());
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.repository.query;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Interface for components being able to provide {@link EntityInformationCreator} for a given {@link Class}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface EntityInformationCreator {
|
||||
|
||||
/**
|
||||
* Returns a {@link MongoEntityInformation} for the given domain class.
|
||||
*
|
||||
* @param domainClass the domain class to create the {@link MongoEntityInformation} for, must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
<T, ID extends Serializable> MongoEntityInformation<T, ID> getEntityInformation(Class<T> domainClass);
|
||||
|
||||
/**
|
||||
* Returns a {@link MongoEntityInformation} for the given domain class and class to retrieve the collection to query
|
||||
* against from.
|
||||
*
|
||||
* @param domainClass the domain class to create the {@link MongoEntityInformation} for, must not be {@literal null}.
|
||||
* @param collectionClass the class to derive the collection from queries to retrieve the domain classes from shall be
|
||||
* ran against, must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
<T, ID extends Serializable> MongoEntityInformation<T, ID> getEntityInformation(Class<T> domainClass,
|
||||
Class<?> collectionClass);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.repository.query;
|
||||
|
||||
import org.springframework.data.repository.core.EntityMetadata;
|
||||
|
||||
/**
|
||||
* Extension of {@link EntityMetadata} to additionally expose the collection name an entity shall be persisted to.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface MongoEntityMetadata<T> extends EntityMetadata<T> {
|
||||
|
||||
/**
|
||||
* Returns the name of the collection the entity shall be persisted to.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String getCollectionName();
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,9 +20,12 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mongodb.core.geo.GeoPage;
|
||||
import org.springframework.data.mongodb.core.geo.GeoResult;
|
||||
import org.springframework.data.mongodb.core.geo.GeoResults;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
import org.springframework.data.mongodb.repository.Query;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.query.Parameters;
|
||||
@@ -33,8 +36,7 @@ import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* TODO - Extract methods for {@link #getAnnotatedQuery()} into superclass as it is currently copied from Spring Data
|
||||
* JPA
|
||||
* Mongo specific implementation of {@link QueryMethod}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@@ -45,19 +47,24 @@ public class MongoQueryMethod extends QueryMethod {
|
||||
.asList(GeoResult.class, GeoResults.class, GeoPage.class);
|
||||
|
||||
private final Method method;
|
||||
private final MongoEntityInformation<?, ?> entityInformation;
|
||||
private final MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
|
||||
|
||||
private MongoEntityMetadata<?> metadata;
|
||||
|
||||
/**
|
||||
* Creates a new {@link MongoQueryMethod} from the given {@link Method}.
|
||||
*
|
||||
* @param method
|
||||
*/
|
||||
public MongoQueryMethod(Method method, RepositoryMetadata metadata, EntityInformationCreator entityInformationCreator) {
|
||||
public MongoQueryMethod(Method method, RepositoryMetadata metadata,
|
||||
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext) {
|
||||
|
||||
super(method, metadata);
|
||||
Assert.notNull(entityInformationCreator, "DefaultEntityInformationCreator must not be null!");
|
||||
|
||||
Assert.notNull(mappingContext, "MappingContext must not be null!");
|
||||
|
||||
this.method = method;
|
||||
this.entityInformation = entityInformationCreator.getEntityInformation(metadata.getReturnedDomainClass(method),
|
||||
getDomainClass());
|
||||
this.mappingContext = mappingContext;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -101,14 +108,30 @@ public class MongoQueryMethod extends QueryMethod {
|
||||
return StringUtils.hasText(value) ? value : null;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.query.QueryMethod#getEntityInformation()
|
||||
*/
|
||||
@Override
|
||||
public MongoEntityInformation<?, ?> getEntityInformation() {
|
||||
@SuppressWarnings("unchecked")
|
||||
public MongoEntityMetadata<?> getEntityInformation() {
|
||||
|
||||
return entityInformation;
|
||||
if (metadata == null) {
|
||||
|
||||
Class<?> returnedObjectType = getReturnedObjectType();
|
||||
Class<?> domainClass = getDomainClass();
|
||||
|
||||
MongoPersistentEntity<?> returnedEntity = mappingContext.getPersistentEntity(getReturnedObjectType());
|
||||
MongoPersistentEntity<?> managedEntity = mappingContext.getPersistentEntity(domainClass);
|
||||
returnedEntity = returnedEntity == null ? managedEntity : returnedEntity;
|
||||
MongoPersistentEntity<?> collectionEntity = domainClass.isAssignableFrom(returnedObjectType) ? returnedEntity
|
||||
: managedEntity;
|
||||
|
||||
this.metadata = new SimpleMongoEntityMetadata<Object>((Class<Object>) returnedEntity.getType(),
|
||||
collectionEntity.getCollection());
|
||||
}
|
||||
|
||||
return this.metadata;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -121,12 +144,11 @@ public class MongoQueryMethod extends QueryMethod {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether te query is a geoNear query.
|
||||
* Returns whether te query is a geo near query.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isGeoNearQuery() {
|
||||
|
||||
return isGeoNearQuery(this.method);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.repository.query;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Bean based implementation of {@link MongoEntityMetadata}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
class SimpleMongoEntityMetadata<T> implements MongoEntityMetadata<T> {
|
||||
|
||||
private final Class<T> type;
|
||||
private final String collectionName;
|
||||
|
||||
/**
|
||||
* Creates a new {@link SimpleMongoEntityMetadata} using the given type and collection name.
|
||||
*
|
||||
* @param type must not be {@literal null}.
|
||||
* @param collectionName must not be {@literal null} or empty.
|
||||
*/
|
||||
public SimpleMongoEntityMetadata(Class<T> type, String collectionName) {
|
||||
|
||||
Assert.notNull(type, "Type must not be null!");
|
||||
Assert.hasText(collectionName, "Collection name must not be null or empty!");
|
||||
|
||||
this.type = type;
|
||||
this.collectionName = collectionName;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.core.EntityMetadata#getJavaType()
|
||||
*/
|
||||
public Class<T> getJavaType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.repository.query.MongoEntityMetadata#getCollectionName()
|
||||
*/
|
||||
public String getCollectionName() {
|
||||
return collectionName;
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.repository.support;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
import org.springframework.data.mongodb.repository.query.EntityInformationCreator;
|
||||
import org.springframework.data.mongodb.repository.query.MongoEntityInformation;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Simple {@link EntityInformationCreator} to to create {@link MongoEntityInformation} instances based on a
|
||||
* {@link MappingContext}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class DefaultEntityInformationCreator implements EntityInformationCreator {
|
||||
|
||||
private final MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
|
||||
|
||||
public DefaultEntityInformationCreator(
|
||||
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext) {
|
||||
Assert.notNull(mappingContext);
|
||||
this.mappingContext = mappingContext;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.repository.support.EntityInformationCreator#getEntityInformation(java.lang.Class)
|
||||
*/
|
||||
public <T, ID extends Serializable> MongoEntityInformation<T, ID> getEntityInformation(Class<T> domainClass) {
|
||||
return getEntityInformation(domainClass, null);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.repository.support.EntityInformationCreator#getEntityInformation(java.lang.Class, java.lang.Class)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T, ID extends Serializable> MongoEntityInformation<T, ID> getEntityInformation(Class<T> domainClass,
|
||||
Class<?> collectionClass) {
|
||||
|
||||
MongoPersistentEntity<T> persistentEntity = (MongoPersistentEntity<T>) mappingContext
|
||||
.getPersistentEntity(domainClass);
|
||||
String customCollectionName = collectionClass == null ? null : mappingContext.getPersistentEntity(collectionClass)
|
||||
.getCollection();
|
||||
|
||||
return new MappingMongoEntityInformation<T, ID>(persistentEntity, customCollectionName);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -25,7 +25,7 @@ import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.mongodb.core.MongoOperations;
|
||||
import org.springframework.data.mongodb.core.index.Index;
|
||||
import org.springframework.data.mongodb.core.query.Order;
|
||||
import org.springframework.data.mongodb.repository.query.MongoEntityInformation;
|
||||
import org.springframework.data.mongodb.repository.query.MongoEntityMetadata;
|
||||
import org.springframework.data.mongodb.repository.query.PartTreeMongoQuery;
|
||||
import org.springframework.data.mongodb.repository.query.QueryUtils;
|
||||
import org.springframework.data.repository.core.support.QueryCreationListener;
|
||||
@@ -85,7 +85,7 @@ class IndexEnsuringQueryCreationListener implements QueryCreationListener<PartTr
|
||||
}
|
||||
}
|
||||
|
||||
MongoEntityInformation<?, ?> metadata = query.getQueryMethod().getEntityInformation();
|
||||
MongoEntityMetadata<?> metadata = query.getQueryMethod().getEntityInformation();
|
||||
operations.indexOps(metadata.getCollectionName()).ensureIndex(index);
|
||||
LOG.debug(String.format("Created %s!", index));
|
||||
}
|
||||
@@ -99,4 +99,4 @@ class IndexEnsuringQueryCreationListener implements QueryCreationListener<PartTr
|
||||
org.springframework.data.domain.Sort.Order order = sort.getOrderFor(property);
|
||||
return order == null ? Order.DESCENDING : order.isAscending() ? Order.ASCENDING : Order.DESCENDING;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2011 the original author or authors.
|
||||
* Copyright 2010-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,10 +21,11 @@ import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.mongodb.core.MongoOperations;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
import org.springframework.data.mongodb.repository.MongoRepository;
|
||||
import org.springframework.data.mongodb.repository.query.EntityInformationCreator;
|
||||
import org.springframework.data.mongodb.repository.query.MongoEntityInformation;
|
||||
import org.springframework.data.mongodb.repository.query.MongoQueryMethod;
|
||||
import org.springframework.data.mongodb.repository.query.PartTreeMongoQuery;
|
||||
@@ -46,20 +47,18 @@ import org.springframework.util.Assert;
|
||||
public class MongoRepositoryFactory extends RepositoryFactorySupport {
|
||||
|
||||
private final MongoOperations mongoOperations;
|
||||
private final EntityInformationCreator entityInformationCreator;
|
||||
private final MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
|
||||
|
||||
/**
|
||||
* Creates a new {@link MongoRepositoryFactory} with the given {@link MongoTemplate} and {@link MappingContext}.
|
||||
* Creates a new {@link MongoRepositoryFactory} with the given {@link MongoOperations}.
|
||||
*
|
||||
* @param template must not be {@literal null}
|
||||
* @param mappingContext
|
||||
* @param mongoOperations must not be {@literal null}
|
||||
*/
|
||||
public MongoRepositoryFactory(MongoOperations mongoOperations) {
|
||||
|
||||
Assert.notNull(mongoOperations);
|
||||
this.mongoOperations = mongoOperations;
|
||||
this.entityInformationCreator = new DefaultEntityInformationCreator(mongoOperations.getConverter()
|
||||
.getMappingContext());
|
||||
this.mappingContext = mongoOperations.getConverter().getMappingContext();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -117,7 +116,7 @@ public class MongoRepositoryFactory extends RepositoryFactorySupport {
|
||||
*/
|
||||
public RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, NamedQueries namedQueries) {
|
||||
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, entityInformationCreator);
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, mappingContext);
|
||||
String namedQueryName = queryMethod.getNamedQueryName();
|
||||
|
||||
if (namedQueries.hasQuery(namedQueryName)) {
|
||||
@@ -136,7 +135,16 @@ public class MongoRepositoryFactory extends RepositoryFactorySupport {
|
||||
* @see org.springframework.data.repository.core.support.RepositoryFactorySupport#getEntityInformation(java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T, ID extends Serializable> MongoEntityInformation<T, ID> getEntityInformation(Class<T> domainClass) {
|
||||
return entityInformationCreator.getEntityInformation(domainClass);
|
||||
|
||||
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(domainClass);
|
||||
|
||||
if (entity == null) {
|
||||
throw new MappingException(String.format("Could not lookup mapping metadata for domain class %s!",
|
||||
domainClass.getName()));
|
||||
}
|
||||
|
||||
return new MappingMongoEntityInformation<T, ID>((MongoPersistentEntity<T>) entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.authentication.UserCredentials;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolExecutorFactoryBean;
|
||||
|
||||
import com.mongodb.DB;
|
||||
import com.mongodb.Mongo;
|
||||
import com.mongodb.MongoException;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link MongoDbUtils}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class MongoDbUtilsIntegrationTests {
|
||||
|
||||
static final String DATABASE_NAME = "dbAuthTests";
|
||||
static final UserCredentials CREDENTIALS = new UserCredentials("admin", "admin");
|
||||
|
||||
static Mongo mongo;
|
||||
static MongoTemplate template;
|
||||
static ThreadPoolExecutorFactoryBean factory;
|
||||
static ExecutorService service;
|
||||
|
||||
Exception exception;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUp() throws Exception {
|
||||
|
||||
mongo = new Mongo();
|
||||
template = new MongoTemplate(mongo, DATABASE_NAME);
|
||||
|
||||
// Create sample user
|
||||
template.execute(new DbCallback<Void>() {
|
||||
public Void doInDB(DB db) throws MongoException, DataAccessException {
|
||||
db.addUser("admin", "admin".toCharArray());
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
factory = new ThreadPoolExecutorFactoryBean();
|
||||
factory.setCorePoolSize(2);
|
||||
factory.setMaxPoolSize(10);
|
||||
factory.setWaitForTasksToCompleteOnShutdown(true);
|
||||
factory.afterPropertiesSet();
|
||||
|
||||
service = factory.getObject();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDown() {
|
||||
|
||||
factory.destroy();
|
||||
|
||||
// Remove test database
|
||||
|
||||
template.execute(new DbCallback<Void>() {
|
||||
public Void doInDB(DB db) throws MongoException, DataAccessException {
|
||||
db.dropDatabase();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-585
|
||||
*/
|
||||
@Test
|
||||
public void authenticatesCorrectlyInMultithreadedEnvironment() throws Exception {
|
||||
|
||||
Callable<Void> callable = new Callable<Void>() {
|
||||
public Void call() throws Exception {
|
||||
|
||||
try {
|
||||
DB db = MongoDbUtils.getDB(mongo, DATABASE_NAME, CREDENTIALS);
|
||||
assertThat(db, is(notNullValue()));
|
||||
} catch (Exception o_O) {
|
||||
MongoDbUtilsIntegrationTests.this.exception = o_O;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
List<Callable<Void>> callables = new ArrayList<Callable<Void>>();
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
callables.add(callable);
|
||||
}
|
||||
|
||||
service.invokeAll(callables);
|
||||
|
||||
if (exception != null) {
|
||||
fail("Exception occurred!" + exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.NestedRuntimeException;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.dao.InvalidDataAccessResourceUsageException;
|
||||
import org.springframework.data.mongodb.UncategorizedMongoDbException;
|
||||
|
||||
import com.mongodb.MongoException;
|
||||
import com.mongodb.MongoException.DuplicateKey;
|
||||
import com.mongodb.MongoException.Network;
|
||||
import com.mongodb.MongoInternalException;
|
||||
import com.mongodb.ServerAddress;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link MongoExceptionTranslator}.
|
||||
*
|
||||
* @author Michal Vich
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class MongoExceptionTranslatorUnitTests {
|
||||
|
||||
MongoExceptionTranslator translator;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
translator = new MongoExceptionTranslator();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void translateDuplicateKey() {
|
||||
|
||||
DuplicateKey exception = new DuplicateKey(1, "Duplicated key");
|
||||
DataAccessException translatedException = translator.translateExceptionIfPossible(exception);
|
||||
|
||||
expectExceptionWithCauseMessage(translatedException, DuplicateKeyException.class, "Duplicated key");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void translateNetwork() {
|
||||
|
||||
Network exception = new Network("IOException", new IOException("IOException"));
|
||||
DataAccessException translatedException = translator.translateExceptionIfPossible(exception);
|
||||
|
||||
expectExceptionWithCauseMessage(translatedException, DataAccessResourceFailureException.class, "IOException");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void translateCursorNotFound() throws UnknownHostException {
|
||||
|
||||
MongoException.CursorNotFound exception = new MongoException.CursorNotFound(1, new ServerAddress());
|
||||
DataAccessException translatedException = translator.translateExceptionIfPossible(exception);
|
||||
|
||||
expectExceptionWithCauseMessage(translatedException, DataAccessResourceFailureException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void translateToDuplicateKeyException() {
|
||||
|
||||
checkTranslatedMongoException(DuplicateKeyException.class, 11000);
|
||||
checkTranslatedMongoException(DuplicateKeyException.class, 11001);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void translateToDataAccessResourceFailureException() {
|
||||
|
||||
checkTranslatedMongoException(DataAccessResourceFailureException.class, 12000);
|
||||
checkTranslatedMongoException(DataAccessResourceFailureException.class, 13440);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void translateToInvalidDataAccessApiUsageException() {
|
||||
|
||||
checkTranslatedMongoException(InvalidDataAccessApiUsageException.class, 10003);
|
||||
checkTranslatedMongoException(InvalidDataAccessApiUsageException.class, 12001);
|
||||
checkTranslatedMongoException(InvalidDataAccessApiUsageException.class, 12010);
|
||||
checkTranslatedMongoException(InvalidDataAccessApiUsageException.class, 12011);
|
||||
checkTranslatedMongoException(InvalidDataAccessApiUsageException.class, 12012);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void translateToUncategorizedMongoDbException() {
|
||||
|
||||
MongoException exception = new MongoException(0, "");
|
||||
DataAccessException translatedException = translator.translateExceptionIfPossible(exception);
|
||||
|
||||
expectExceptionWithCauseMessage(translatedException, UncategorizedMongoDbException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void translateMongoInternalException() {
|
||||
|
||||
MongoInternalException exception = new MongoInternalException("Internal exception");
|
||||
DataAccessException translatedException = translator.translateExceptionIfPossible(exception);
|
||||
|
||||
expectExceptionWithCauseMessage(translatedException, InvalidDataAccessResourceUsageException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void translateUnsupportedException() {
|
||||
|
||||
RuntimeException exception = new RuntimeException();
|
||||
assertThat(translator.translateExceptionIfPossible(exception), is(nullValue()));
|
||||
}
|
||||
|
||||
private void checkTranslatedMongoException(Class<? extends Exception> clazz, int code) {
|
||||
|
||||
try {
|
||||
translator.translateExceptionIfPossible(new MongoException(code, ""));
|
||||
fail("Expected exception of type " + clazz.getName() + "!");
|
||||
} catch (NestedRuntimeException e) {
|
||||
Throwable cause = e.getRootCause();
|
||||
assertThat(cause, is(instanceOf(MongoException.class)));
|
||||
assertThat(((MongoException) cause).getCode(), is(code));
|
||||
}
|
||||
}
|
||||
|
||||
private static void expectExceptionWithCauseMessage(NestedRuntimeException e,
|
||||
Class<? extends NestedRuntimeException> type) {
|
||||
expectExceptionWithCauseMessage(e, type, null);
|
||||
}
|
||||
|
||||
private static void expectExceptionWithCauseMessage(NestedRuntimeException e,
|
||||
Class<? extends NestedRuntimeException> type, String message) {
|
||||
|
||||
assertThat(e, is(instanceOf(type)));
|
||||
|
||||
if (message != null) {
|
||||
assertThat(e.getRootCause(), is(notNullValue()));
|
||||
assertThat(e.getRootCause().getMessage(), containsString(message));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
* Copyright 2011-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -34,6 +34,7 @@ import org.springframework.data.mongodb.core.geo.Point;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
import org.springframework.data.mongodb.core.query.NearQuery;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DBObject;
|
||||
@@ -78,7 +79,7 @@ public abstract class MongoOperationsUnitTests {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object convertToMongoType(Object obj) {
|
||||
public Object convertToMongoType(Object obj, TypeInformation<?> typeInformation) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -212,19 +212,14 @@ public class MongoTemplateTests {
|
||||
|
||||
template.insert(person);
|
||||
|
||||
try {
|
||||
thrown.expect(DataIntegrityViolationException.class);
|
||||
thrown.expectMessage("Execution");
|
||||
thrown.expectMessage("$push");
|
||||
thrown.expectMessage("firstName");
|
||||
|
||||
Query query = new Query(Criteria.where("firstName").is("Amol"));
|
||||
Update upd = new Update().push("age", 29);
|
||||
template.updateFirst(query, upd, Person.class);
|
||||
fail("Expected DataIntegrityViolationException!");
|
||||
|
||||
} catch (DataIntegrityViolationException e) {
|
||||
|
||||
assertThat(e.getMessage(),
|
||||
is("Execution of update with '{ \"$push\" : { \"age\" : 29}}'' using '{ \"firstName\" : \"Amol\"}' "
|
||||
+ "query failed: Cannot apply $push/$pushAll modifier to non-array"));
|
||||
}
|
||||
Query query = new Query(Criteria.where("firstName").is("Amol"));
|
||||
Update upd = new Update().push("age", 29);
|
||||
template.updateFirst(query, upd, Person.class);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1028,7 +1023,7 @@ public class MongoTemplateTests {
|
||||
assertThat(lastMongoAction.getCollectionName(), is("personWithIdPropertyOfTypeObjectId"));
|
||||
assertThat(lastMongoAction.getDefaultWriteConcern(), equalTo(WriteConcern.NONE));
|
||||
assertThat(lastMongoAction.getDocument(), notNullValue());
|
||||
assertThat(lastMongoAction.getEntityClass().toString(), is(PersonWithIdPropertyOfTypeObjectId.class.toString()));
|
||||
assertThat(lastMongoAction.getEntityType().toString(), is(PersonWithIdPropertyOfTypeObjectId.class.toString()));
|
||||
assertThat(lastMongoAction.getMongoActionOperation(), is(MongoActionOperation.UPDATE));
|
||||
assertThat(lastMongoAction.getQuery(), equalTo(q.getQueryObject()));
|
||||
|
||||
@@ -1422,6 +1417,44 @@ public class MongoTemplateTests {
|
||||
template.save("Foobar!", "collection");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-588
|
||||
*/
|
||||
@Test
|
||||
public void initializesVersionOnInsert() {
|
||||
|
||||
PersonWithVersionPropertyOfTypeInteger person = new PersonWithVersionPropertyOfTypeInteger();
|
||||
person.firstName = "Dave";
|
||||
|
||||
template.insert(person);
|
||||
|
||||
assertThat(person.version, is(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-588
|
||||
*/
|
||||
@Test
|
||||
public void initializesVersionOnBatchInsert() {
|
||||
|
||||
PersonWithVersionPropertyOfTypeInteger person = new PersonWithVersionPropertyOfTypeInteger();
|
||||
person.firstName = "Dave";
|
||||
|
||||
template.insertAll(Arrays.asList(person));
|
||||
|
||||
assertThat(person.version, is(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-568
|
||||
*/
|
||||
@Test
|
||||
public void queryCantBeNull() {
|
||||
|
||||
List<PersonWithIdPropertyOfTypeObjectId> result = template.findAll(PersonWithIdPropertyOfTypeObjectId.class);
|
||||
assertThat(template.find(null, PersonWithIdPropertyOfTypeObjectId.class), is(result));
|
||||
}
|
||||
|
||||
static class MyId {
|
||||
|
||||
String first;
|
||||
|
||||
@@ -335,6 +335,18 @@ public class QueryMapperUnitTests {
|
||||
assertThat(reference.containsField("$in"), is(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-570
|
||||
*/
|
||||
@Test
|
||||
public void correctlyConvertsNullReference() {
|
||||
|
||||
Query query = query(where("reference").is(null));
|
||||
DBObject object = mapper.getMappedObject(query.getQueryObject(), context.getPersistentEntity(WithDBRef.class));
|
||||
|
||||
assertThat(object.get("reference"), is(nullValue()));
|
||||
}
|
||||
|
||||
class IdWrapper {
|
||||
Object id;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
* Copyright 2011-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -523,4 +523,23 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
|
||||
assertThat(result, hasSize(1));
|
||||
assertThat(result, hasItem(oliver));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-600
|
||||
*/
|
||||
@Test
|
||||
public void readsDocumentsWithNestedPolymorphismCorrectly() {
|
||||
|
||||
UsernameAndPassword usernameAndPassword = new UsernameAndPassword();
|
||||
usernameAndPassword.username = "dave";
|
||||
usernameAndPassword.password = "btcs";
|
||||
|
||||
dave.credentials = usernameAndPassword;
|
||||
|
||||
repository.save(dave);
|
||||
|
||||
List<Person> result = repository.findByCredentials(usernameAndPassword);
|
||||
assertThat(result, hasSize(1));
|
||||
assertThat(result, hasItem(dave));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.repository;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface Credentials {
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2011 the original author or authors.
|
||||
* Copyright 2010-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -54,6 +54,8 @@ public class Person extends Contact {
|
||||
@DBRef
|
||||
User creator;
|
||||
|
||||
Credentials credentials;
|
||||
|
||||
public Person() {
|
||||
|
||||
this(null, null);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2012 the original author or authors.
|
||||
* Copyright 2010-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -192,4 +192,10 @@ public interface PersonRepository extends MongoRepository<Person, String>, Query
|
||||
*/
|
||||
List<Person> findByLastnameNot(String lastname);
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-600
|
||||
* @param credentials
|
||||
* @return
|
||||
*/
|
||||
List<Person> findByCredentials(Credentials credentials);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.repository;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class UsernameAndPassword implements Credentials {
|
||||
|
||||
String username;
|
||||
String password;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -27,7 +27,6 @@ import org.springframework.data.mongodb.core.geo.Metrics;
|
||||
import org.springframework.data.mongodb.core.geo.Point;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||
import org.springframework.data.mongodb.repository.Person;
|
||||
import org.springframework.data.mongodb.repository.support.DefaultEntityInformationCreator;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.core.support.DefaultRepositoryMetadata;
|
||||
@@ -42,13 +41,12 @@ public class MongoParametersParameterAccessorUnitTests {
|
||||
private static final Distance DISTANCE = new Distance(2.5, Metrics.KILOMETERS);
|
||||
private static final RepositoryMetadata metadata = new DefaultRepositoryMetadata(PersonRepository.class);
|
||||
private static final MongoMappingContext context = new MongoMappingContext();
|
||||
private static final EntityInformationCreator creator = new DefaultEntityInformationCreator(context);
|
||||
|
||||
@Test
|
||||
public void returnsNullForDistanceIfNoneAvailable() throws NoSuchMethodException, SecurityException {
|
||||
|
||||
Method method = PersonRepository.class.getMethod("findByLocationNear", Point.class);
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, creator);
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, context);
|
||||
|
||||
MongoParameterAccessor accessor = new MongoParametersParameterAccessor(queryMethod,
|
||||
new Object[] { new Point(10, 20) });
|
||||
@@ -59,7 +57,7 @@ public class MongoParametersParameterAccessorUnitTests {
|
||||
public void returnsDistanceIfAvailable() throws NoSuchMethodException, SecurityException {
|
||||
|
||||
Method method = PersonRepository.class.getMethod("findByLocationNear", Point.class, Distance.class);
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, creator);
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, context);
|
||||
|
||||
MongoParameterAccessor accessor = new MongoParametersParameterAccessor(queryMethod, new Object[] {
|
||||
new Point(10, 20), DISTANCE });
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
* Copyright 2011-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -46,10 +46,10 @@ import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
import org.springframework.data.mongodb.core.query.Criteria;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.data.mongodb.repository.support.DefaultEntityInformationCreator;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.core.support.DefaultRepositoryMetadata;
|
||||
import org.springframework.data.repository.query.parser.PartTree;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
|
||||
/**
|
||||
* Unit test for {@link MongoQueryCreator}.
|
||||
@@ -75,7 +75,7 @@ public class MongoQueryCreatorUnitTests {
|
||||
public Object answer(InvocationOnMock invocation) throws Throwable {
|
||||
return invocation.getArguments()[0];
|
||||
}
|
||||
}).when(converter).convertToMongoType(any());
|
||||
}).when(converter).convertToMongoType(any(), Mockito.any(TypeInformation.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -301,7 +301,7 @@ public class MongoQueryCreatorUnitTests {
|
||||
Method method = PersonRepository.class.getMethod("findByLocationNearAndFirstname", Point.class, Distance.class,
|
||||
String.class);
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, new DefaultRepositoryMetadata(PersonRepository.class),
|
||||
new DefaultEntityInformationCreator(new MongoMappingContext()));
|
||||
new MongoMappingContext());
|
||||
MongoParameterAccessor accessor = new MongoParametersParameterAccessor(queryMethod, new Object[] { point, distance,
|
||||
"Dave" });
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) 2011 by the original author(s).
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -35,7 +35,6 @@ import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||
import org.springframework.data.mongodb.repository.Address;
|
||||
import org.springframework.data.mongodb.repository.Contact;
|
||||
import org.springframework.data.mongodb.repository.Person;
|
||||
import org.springframework.data.mongodb.repository.support.DefaultEntityInformationCreator;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.core.support.DefaultRepositoryMetadata;
|
||||
|
||||
@@ -46,12 +45,11 @@ import org.springframework.data.repository.core.support.DefaultRepositoryMetadat
|
||||
*/
|
||||
public class MongoQueryMethodUnitTests {
|
||||
|
||||
EntityInformationCreator creator;
|
||||
MongoMappingContext context;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MongoMappingContext context = new MongoMappingContext();
|
||||
creator = new DefaultEntityInformationCreator(context);
|
||||
context = new MongoMappingContext();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -60,11 +58,11 @@ public class MongoQueryMethodUnitTests {
|
||||
Method method = SampleRepository.class.getMethod("method");
|
||||
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, new DefaultRepositoryMetadata(SampleRepository.class),
|
||||
creator);
|
||||
MongoEntityInformation<?, ?> entityInformation = queryMethod.getEntityInformation();
|
||||
context);
|
||||
MongoEntityMetadata<?> metadata = queryMethod.getEntityInformation();
|
||||
|
||||
assertThat(entityInformation.getJavaType(), is(typeCompatibleWith(Address.class)));
|
||||
assertThat(entityInformation.getCollectionName(), is("contact"));
|
||||
assertThat(metadata.getJavaType(), is(typeCompatibleWith(Address.class)));
|
||||
assertThat(metadata.getCollectionName(), is("contact"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -73,8 +71,8 @@ public class MongoQueryMethodUnitTests {
|
||||
Method method = SampleRepository2.class.getMethod("method");
|
||||
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, new DefaultRepositoryMetadata(SampleRepository.class),
|
||||
creator);
|
||||
MongoEntityInformation<?, ?> entityInformation = queryMethod.getEntityInformation();
|
||||
context);
|
||||
MongoEntityMetadata<?> entityInformation = queryMethod.getEntityInformation();
|
||||
|
||||
assertThat(entityInformation.getJavaType(), is(typeCompatibleWith(Person.class)));
|
||||
assertThat(entityInformation.getCollectionName(), is("person"));
|
||||
@@ -103,7 +101,7 @@ public class MongoQueryMethodUnitTests {
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsNullEntityCreator() throws Exception {
|
||||
public void rejectsNullMappingContext() throws Exception {
|
||||
Method method = PersonRepository.class.getMethod("findByFirstname", String.class, Point.class);
|
||||
new MongoQueryMethod(method, new DefaultRepositoryMetadata(PersonRepository.class), null);
|
||||
}
|
||||
@@ -115,9 +113,16 @@ public class MongoQueryMethodUnitTests {
|
||||
assertThat(method.isCollectionQuery(), is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createsMongoQueryMethodObjectForMethodReturningAnInterface() throws Exception {
|
||||
|
||||
Method method = SampleRepository2.class.getMethod("methodReturningAnInterface");
|
||||
new MongoQueryMethod(method, new DefaultRepositoryMetadata(SampleRepository2.class), context);
|
||||
}
|
||||
|
||||
private MongoQueryMethod queryMethod(String name, Class<?>... parameters) throws Exception {
|
||||
Method method = PersonRepository.class.getMethod(name, parameters);
|
||||
return new MongoQueryMethod(method, new DefaultRepositoryMetadata(PersonRepository.class), creator);
|
||||
return new MongoQueryMethod(method, new DefaultRepositoryMetadata(PersonRepository.class), context);
|
||||
}
|
||||
|
||||
interface PersonRepository extends Repository<User, Long> {
|
||||
@@ -142,5 +147,11 @@ public class MongoQueryMethodUnitTests {
|
||||
interface SampleRepository2 extends Repository<Contact, Long> {
|
||||
|
||||
List<Person> method();
|
||||
|
||||
Customer methodReturningAnInterface();
|
||||
}
|
||||
|
||||
interface Customer {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -54,8 +54,6 @@ public class StringBasedMongoQueryUnitTests {
|
||||
@Mock
|
||||
RepositoryMetadata metadata;
|
||||
@Mock
|
||||
EntityInformationCreator creator;
|
||||
@Mock
|
||||
MongoDbFactory factory;
|
||||
|
||||
MongoConverter converter;
|
||||
@@ -70,7 +68,7 @@ public class StringBasedMongoQueryUnitTests {
|
||||
public void bindsSimplePropertyCorrectly() throws Exception {
|
||||
|
||||
Method method = SampleRepository.class.getMethod("findByLastname", String.class);
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, creator);
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, converter.getMappingContext());
|
||||
StringBasedMongoQuery mongoQuery = new StringBasedMongoQuery(queryMethod, operations);
|
||||
ConvertingParameterAccessor accesor = StubParameterAccessor.getAccessor(converter, "Matthews");
|
||||
|
||||
@@ -132,7 +130,7 @@ public class StringBasedMongoQueryUnitTests {
|
||||
private StringBasedMongoQuery createQueryForMethod(String name, Class<?>... parameters) throws Exception {
|
||||
|
||||
Method method = SampleRepository.class.getMethod(name, parameters);
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, creator);
|
||||
MongoQueryMethod queryMethod = new MongoQueryMethod(method, metadata, converter.getMappingContext());
|
||||
return new StringBasedMongoQuery(queryMethod, operations);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
log4j.rootCategory=ERROR, stdout
|
||||
|
||||
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %40.40c:%4L - %m%n
|
||||
|
||||
#log4j.category.org.springframework.data=DEBUG
|
||||
|
||||
log4j.category.org.hibernate.SQL=DEBUG
|
||||
# for debugging datasource initialization
|
||||
# log4j.category.test.jdbc=DEBUG
|
||||
18
spring-data-mongodb/src/test/resources/logback.xml
Normal file
18
spring-data-mongodb/src/test/resources/logback.xml
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
|
||||
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d %5p %40.40c:%4L - %m%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!--
|
||||
<logger name="org.springframework" level="debug" />
|
||||
-->
|
||||
|
||||
<root level="error">
|
||||
<appender-ref ref="console" />
|
||||
</root>
|
||||
|
||||
</configuration>
|
||||
@@ -0,0 +1 @@
|
||||
handlers = org.slf4j.bridge.SLF4JBridgeHandler
|
||||
@@ -1,5 +1,29 @@
|
||||
Spring Data MongoDB Changelog
|
||||
=============================================
|
||||
=============================
|
||||
|
||||
Changes in version 1.1.2.GA (2013-02-08)
|
||||
----------------------------------------
|
||||
** Bug
|
||||
* [DATAMONGO-562] - Cannot create entity with OptimisticLocking (@Version) and initial id
|
||||
* [DATAMONGO-568] - MongoTemplate.find(...) method causes Nullpointer if query parameter is null
|
||||
* [DATAMONGO-570] - Query methods on @DBRef field with the qualifier isNull throws Exception
|
||||
* [DATAMONGO-578] - pom version issues in 1.1.x branch
|
||||
* [DATAMONGO-583] - Check if you are using for loop with a DBCursor
|
||||
* [DATAMONGO-585] - Exception during authentication in multithreaded access
|
||||
* [DATAMONGO-588] - MongoTemplate.insert does not initialize null versions to zero
|
||||
* [DATAMONGO-600] - Issues with polymorphism of nested types
|
||||
* [DATAMONGO-601] - CannotGetMongoDbConnectionException should not print password in logfile
|
||||
|
||||
** Improvement
|
||||
* [DATAMONGO-573] - Move to Logback for test logging
|
||||
* [DATAMONGO-580] - Polish BeanDefinitionParsers to avoid warnings in STS
|
||||
|
||||
** Task
|
||||
* [DATAMONGO-81] - Create unit tests for exception translation in MongoTemplate
|
||||
* [DATAMONGO-563] - Upgrade to MongoDB driver 2.9.2 as it fixes a serious regression introduced in 2.9.0
|
||||
* [DATAMONGO-576] - Configure java.util.logging to reduce verbose test logging
|
||||
* [DATAMONGO-590] - Clean up code in MongoTemplate
|
||||
* [DATAMONGO-608] - Release 1.1.2
|
||||
|
||||
Changes in version 1.1.1.GA (2012-10-17)
|
||||
----------------------------------------
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Spring Data Document 1.0
|
||||
Copyright (c) [2010-2011] SpringSource, a division of VMware, Inc.
|
||||
Spring Data Document 1.1.2
|
||||
Copyright (c) [2010-2013] SpringSource, a division of VMware, Inc.
|
||||
|
||||
This product is licensed to you under the Apache License, Version 2.0 (the "License").
|
||||
You may not use this product except in compliance with the License.
|
||||
|
||||
Reference in New Issue
Block a user