Compare commits
43 Commits
1.8.0.RC1
...
1.8.2.RELE
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
437a48ff4a | ||
|
|
583339641d | ||
|
|
8af4bef772 | ||
|
|
b0336c27a9 | ||
|
|
0b492b6c55 | ||
|
|
b3116a523b | ||
|
|
2ba9e5f403 | ||
|
|
8b1805a145 | ||
|
|
5832055840 | ||
|
|
a13e7b8b24 | ||
|
|
a152aa3ce8 | ||
|
|
ca56ea4aea | ||
|
|
284e2f462d | ||
|
|
257bc891dd | ||
|
|
d26db17bf0 | ||
|
|
d760d9cc11 | ||
|
|
be65970710 | ||
|
|
418a4f8b8c | ||
|
|
fa5f93aad5 | ||
|
|
504e14d4a3 | ||
|
|
f68effe155 | ||
|
|
6fc80f287e | ||
|
|
02aed56fd1 | ||
|
|
f1771504f6 | ||
|
|
741a27edae | ||
|
|
e1869abf3f | ||
|
|
c7be5bfcaa | ||
|
|
9968b752e7 | ||
|
|
e001c6bf89 | ||
|
|
913d383b99 | ||
|
|
f446d7e29f | ||
|
|
77dce53c7a | ||
|
|
73f268e7c4 | ||
|
|
075d7d8131 | ||
|
|
206337044a | ||
|
|
55b44ff7aa | ||
|
|
ae48639ae9 | ||
|
|
6b5e78f810 | ||
|
|
3e485e0a88 | ||
|
|
335c78f908 | ||
|
|
b103e4eaf6 | ||
|
|
c4a6c63d23 | ||
|
|
4a4f10f97b |
10
pom.xml
10
pom.xml
@@ -5,7 +5,7 @@
|
||||
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>1.8.0.RC1</version>
|
||||
<version>1.8.2.RELEASE</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>Spring Data MongoDB</name>
|
||||
@@ -15,7 +15,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data.build</groupId>
|
||||
<artifactId>spring-data-parent</artifactId>
|
||||
<version>1.7.0.RC1</version>
|
||||
<version>1.7.2.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
@@ -28,7 +28,7 @@
|
||||
<properties>
|
||||
<project.type>multi</project.type>
|
||||
<dist.id>spring-data-mongodb</dist.id>
|
||||
<springdata.commons>1.11.0.RC1</springdata.commons>
|
||||
<springdata.commons>1.11.2.RELEASE</springdata.commons>
|
||||
<mongo>2.13.0</mongo>
|
||||
<mongo.osgi>2.13.0</mongo.osgi>
|
||||
</properties>
|
||||
@@ -156,8 +156,8 @@
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-libs-milestone</id>
|
||||
<url>https://repo.spring.io/libs-milestone</url>
|
||||
<id>spring-libs-release</id>
|
||||
<url>https://repo.spring.io/libs-release</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>1.8.0.RC1</version>
|
||||
<version>1.8.2.RELEASE</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb</artifactId>
|
||||
<version>1.8.0.RC1</version>
|
||||
<version>1.8.2.RELEASE</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2014 the original author or authors.
|
||||
* Copyright 2011-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -45,7 +45,7 @@ public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
|
||||
private static final String ENTITY_FIELD_NAME = "_entity_field_name";
|
||||
private static final String ENTITY_FIELD_CLASS = "_entity_field_class";
|
||||
|
||||
protected final Logger log = LoggerFactory.getLogger(getClass());
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
private MongoTemplate mongoTemplate;
|
||||
private EntityManagerFactory entityManagerFactory;
|
||||
@@ -88,8 +88,8 @@ public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
|
||||
if (!changeSet.getValues().containsKey(key)) {
|
||||
String className = (String) dbo.get(ENTITY_FIELD_CLASS);
|
||||
if (className == null) {
|
||||
throw new DataIntegrityViolationException("Unble to convert property " + key + ": Invalid metadata, "
|
||||
+ ENTITY_FIELD_CLASS + " not available");
|
||||
throw new DataIntegrityViolationException(
|
||||
"Unble to convert property " + key + ": Invalid metadata, " + ENTITY_FIELD_CLASS + " not available");
|
||||
}
|
||||
Class<?> clazz = ClassUtils.resolveClassName(className, ClassUtils.getDefaultClassLoader());
|
||||
Object value = mongoTemplate.getConverter().read(clazz, dbo);
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>1.8.0.RC1</version>
|
||||
<version>1.8.2.RELEASE</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>1.8.0.RC1</version>
|
||||
<version>1.8.2.RELEASE</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -160,7 +160,7 @@ public class MongoLog4jAppender extends AppenderSkeleton {
|
||||
|
||||
// Copy properties into document
|
||||
Map<Object, Object> props = event.getProperties();
|
||||
if (null != props && props.size() > 0) {
|
||||
if (null != props && !props.isEmpty()) {
|
||||
BasicDBObject propsDbo = new BasicDBObject();
|
||||
for (Map.Entry<Object, Object> entry : props.entrySet()) {
|
||||
propsDbo.put(entry.getKey().toString(), entry.getValue().toString());
|
||||
|
||||
@@ -39,7 +39,7 @@ public class MongoLog4jAppenderIntegrationTests {
|
||||
|
||||
static final String NAME = MongoLog4jAppenderIntegrationTests.class.getName();
|
||||
|
||||
Logger log = Logger.getLogger(NAME);
|
||||
private static final Logger log = Logger.getLogger(NAME);
|
||||
Mongo mongo;
|
||||
DB db;
|
||||
String collection;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>1.8.0.RC1</version>
|
||||
<version>1.8.2.RELEASE</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -18,6 +18,10 @@ package org.springframework.data.mongodb.config;
|
||||
import static org.springframework.data.config.ParsingUtils.*;
|
||||
import static org.springframework.data.mongodb.config.MongoParsingUtils.*;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||
@@ -44,9 +48,21 @@ import com.mongodb.MongoURI;
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Darimont
|
||||
* @author Christoph Strobl
|
||||
* @author Viktor Khoroshko
|
||||
*/
|
||||
public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
|
||||
|
||||
private static final Set<String> MONGO_URI_ALLOWED_ADDITIONAL_ATTRIBUTES;
|
||||
|
||||
static {
|
||||
|
||||
Set<String> mongoUriAllowedAdditionalAttributes = new HashSet<String>();
|
||||
mongoUriAllowedAdditionalAttributes.add("id");
|
||||
mongoUriAllowedAdditionalAttributes.add("write-concern");
|
||||
|
||||
MONGO_URI_ALLOWED_ADDITIONAL_ATTRIBUTES = Collections.unmodifiableSet(mongoUriAllowedAdditionalAttributes);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#resolveId(org.w3c.dom.Element, org.springframework.beans.factory.support.AbstractBeanDefinition, org.springframework.beans.factory.xml.ParserContext)
|
||||
@@ -70,13 +86,10 @@ public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
|
||||
BeanDefinitionBuilder dbFactoryBuilder = BeanDefinitionBuilder.genericBeanDefinition(SimpleMongoDbFactory.class);
|
||||
setPropertyValue(dbFactoryBuilder, element, "write-concern", "writeConcern");
|
||||
|
||||
BeanDefinition mongoUri = getMongoUri(element);
|
||||
BeanDefinition mongoUri = getMongoUri(element, parserContext);
|
||||
|
||||
if (mongoUri != null) {
|
||||
if (element.getAttributes().getLength() >= 2 && !element.hasAttribute("write-concern")) {
|
||||
parserContext.getReaderContext().error("Configure either Mongo URI or details individually!",
|
||||
parserContext.extractSource(element));
|
||||
}
|
||||
|
||||
dbFactoryBuilder.addConstructorArgValue(mongoUri);
|
||||
return getSourceBeanDefinition(dbFactoryBuilder, parserContext, element);
|
||||
}
|
||||
@@ -149,12 +162,15 @@ public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
|
||||
|
||||
/**
|
||||
* Creates a {@link BeanDefinition} for a {@link MongoURI} or {@link MongoClientURI} depending on configured
|
||||
* attributes.
|
||||
* attributes. <br />
|
||||
* Errors when configured element contains {@literal uri} or {@literal client-uri} along with other attributes except
|
||||
* {@literal write-concern} and/or {@literal id}.
|
||||
*
|
||||
* @param element must not be {@literal null}.
|
||||
* @param parserContext
|
||||
* @return {@literal null} in case no client-/uri defined.
|
||||
*/
|
||||
private BeanDefinition getMongoUri(Element element) {
|
||||
private BeanDefinition getMongoUri(Element element, ParserContext parserContext) {
|
||||
|
||||
boolean hasClientUri = element.hasAttribute("client-uri");
|
||||
|
||||
@@ -162,6 +178,21 @@ public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
|
||||
return null;
|
||||
}
|
||||
|
||||
int allowedAttributesCount = 1;
|
||||
for (String attribute : MONGO_URI_ALLOWED_ADDITIONAL_ATTRIBUTES) {
|
||||
|
||||
if (element.hasAttribute(attribute)) {
|
||||
allowedAttributesCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (element.getAttributes().getLength() > allowedAttributesCount) {
|
||||
|
||||
parserContext.getReaderContext().error(
|
||||
"Configure either " + (hasClientUri ? "Mongo Client URI" : "Mongo URI") + " or details individually!",
|
||||
parserContext.extractSource(element));
|
||||
}
|
||||
|
||||
Class<?> type = hasClientUri ? MongoClientURI.class : MongoURI.class;
|
||||
String uri = hasClientUri ? element.getAttribute("client-uri") : element.getAttribute("uri");
|
||||
|
||||
|
||||
@@ -338,9 +338,10 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
DBCursor cursor = collection.find(mappedQuery, mappedFields);
|
||||
QueryCursorPreparer cursorPreparer = new QueryCursorPreparer(query, entityType);
|
||||
|
||||
ReadDbObjectCallback<T> readCallback = new ReadDbObjectCallback<T>(mongoConverter, entityType);
|
||||
ReadDbObjectCallback<T> readCallback = new ReadDbObjectCallback<T>(mongoConverter, entityType, collection
|
||||
.getName());
|
||||
|
||||
return new CloseableIterableCusorAdapter<T>(cursorPreparer.prepare(cursor), exceptionTranslator, readCallback);
|
||||
return new CloseableIterableCursorAdapter<T>(cursorPreparer.prepare(cursor), exceptionTranslator, readCallback);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -444,7 +445,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
DB db = this.getDb();
|
||||
return action.doInDB(db);
|
||||
} catch (RuntimeException e) {
|
||||
throw potentiallyConvertRuntimeException(e);
|
||||
throw potentiallyConvertRuntimeException(e, exceptionTranslator);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -460,7 +461,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
DBCollection collection = getAndPrepareCollection(getDb(), collectionName);
|
||||
return callback.doInCollection(collection);
|
||||
} catch (RuntimeException e) {
|
||||
throw potentiallyConvertRuntimeException(e);
|
||||
throw potentiallyConvertRuntimeException(e, exceptionTranslator);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -637,7 +638,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
results = results == null ? Collections.emptyList() : results;
|
||||
|
||||
DbObjectCallback<GeoResult<T>> callback = new GeoNearResultDbObjectCallback<T>(new ReadDbObjectCallback<T>(
|
||||
mongoConverter, entityClass), near.getMetric());
|
||||
mongoConverter, entityClass, collectionName), near.getMetric());
|
||||
List<GeoResult<T>> result = new ArrayList<GeoResult<T>>(results.size());
|
||||
|
||||
int index = 0;
|
||||
@@ -774,11 +775,17 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
protected WriteConcern prepareWriteConcern(MongoAction mongoAction) {
|
||||
|
||||
WriteConcern wc = writeConcernResolver.resolve(mongoAction);
|
||||
return potentiallyForceAcknowledgedWrite(wc);
|
||||
}
|
||||
|
||||
if (MongoClientVersion.isMongo3Driver()
|
||||
&& ObjectUtils.nullSafeEquals(WriteResultChecking.EXCEPTION, writeResultChecking)
|
||||
&& (wc == null || wc.getW() < 1)) {
|
||||
return WriteConcern.ACKNOWLEDGED;
|
||||
private WriteConcern potentiallyForceAcknowledgedWrite(WriteConcern wc) {
|
||||
|
||||
if (ObjectUtils.nullSafeEquals(WriteResultChecking.EXCEPTION, writeResultChecking)
|
||||
&& MongoClientVersion.isMongo3Driver()) {
|
||||
if (wc == null || wc.getWObject() == null
|
||||
|| (wc.getWObject() instanceof Number && ((Number) wc.getWObject()).intValue() < 1)) {
|
||||
return WriteConcern.ACKNOWLEDGED;
|
||||
}
|
||||
}
|
||||
return wc;
|
||||
}
|
||||
@@ -789,15 +796,15 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
initializeVersionProperty(objectToSave);
|
||||
|
||||
maybeEmitEvent(new BeforeConvertEvent<T>(objectToSave));
|
||||
maybeEmitEvent(new BeforeConvertEvent<T>(objectToSave, collectionName));
|
||||
|
||||
DBObject dbDoc = toDbObject(objectToSave, writer);
|
||||
|
||||
maybeEmitEvent(new BeforeSaveEvent<T>(objectToSave, dbDoc));
|
||||
maybeEmitEvent(new BeforeSaveEvent<T>(objectToSave, dbDoc, collectionName));
|
||||
Object id = insertDBObject(collectionName, dbDoc, objectToSave.getClass());
|
||||
|
||||
populateIdIfNecessary(objectToSave, id);
|
||||
maybeEmitEvent(new AfterSaveEvent<T>(objectToSave, dbDoc));
|
||||
maybeEmitEvent(new AfterSaveEvent<T>(objectToSave, dbDoc, collectionName));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -885,10 +892,10 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
initializeVersionProperty(o);
|
||||
BasicDBObject dbDoc = new BasicDBObject();
|
||||
|
||||
maybeEmitEvent(new BeforeConvertEvent<T>(o));
|
||||
maybeEmitEvent(new BeforeConvertEvent<T>(o, collectionName));
|
||||
writer.write(o, dbDoc);
|
||||
|
||||
maybeEmitEvent(new BeforeSaveEvent<T>(o, dbDoc));
|
||||
maybeEmitEvent(new BeforeSaveEvent<T>(o, dbDoc, collectionName));
|
||||
dbObjectList.add(dbDoc);
|
||||
}
|
||||
List<ObjectId> ids = insertDBObjectList(collectionName, dbObjectList);
|
||||
@@ -896,7 +903,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
for (T obj : batchToSave) {
|
||||
if (i < ids.size()) {
|
||||
populateIdIfNecessary(obj, ids.get(i));
|
||||
maybeEmitEvent(new AfterSaveEvent<T>(obj, dbObjectList.get(i)));
|
||||
maybeEmitEvent(new AfterSaveEvent<T>(obj, dbObjectList.get(i), collectionName));
|
||||
}
|
||||
i++;
|
||||
}
|
||||
@@ -951,14 +958,14 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
BasicDBObject dbObject = new BasicDBObject();
|
||||
|
||||
maybeEmitEvent(new BeforeConvertEvent<T>(objectToSave));
|
||||
maybeEmitEvent(new BeforeConvertEvent<T>(objectToSave, collectionName));
|
||||
this.mongoConverter.write(objectToSave, dbObject);
|
||||
|
||||
maybeEmitEvent(new BeforeSaveEvent<T>(objectToSave, dbObject));
|
||||
maybeEmitEvent(new BeforeSaveEvent<T>(objectToSave, dbObject, collectionName));
|
||||
Update update = Update.fromDBObject(dbObject, ID_FIELD);
|
||||
|
||||
doUpdate(collectionName, query, update, objectToSave.getClass(), false, false);
|
||||
maybeEmitEvent(new AfterSaveEvent<T>(objectToSave, dbObject));
|
||||
maybeEmitEvent(new AfterSaveEvent<T>(objectToSave, dbObject, collectionName));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -966,15 +973,15 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
assertUpdateableIdIfNotSet(objectToSave);
|
||||
|
||||
maybeEmitEvent(new BeforeConvertEvent<T>(objectToSave));
|
||||
maybeEmitEvent(new BeforeConvertEvent<T>(objectToSave, collectionName));
|
||||
|
||||
DBObject dbDoc = toDbObject(objectToSave, writer);
|
||||
|
||||
maybeEmitEvent(new BeforeSaveEvent<T>(objectToSave, dbDoc));
|
||||
maybeEmitEvent(new BeforeSaveEvent<T>(objectToSave, dbDoc, collectionName));
|
||||
Object id = saveDBObject(collectionName, dbDoc, objectToSave.getClass());
|
||||
|
||||
populateIdIfNecessary(objectToSave, id);
|
||||
maybeEmitEvent(new AfterSaveEvent<T>(objectToSave, dbDoc));
|
||||
maybeEmitEvent(new AfterSaveEvent<T>(objectToSave, dbDoc, collectionName));
|
||||
}
|
||||
|
||||
protected Object insertDBObject(final String collectionName, final DBObject dbDoc, final Class<?> entityClass) {
|
||||
@@ -1266,7 +1273,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
return execute(collectionName, new CollectionCallback<WriteResult>() {
|
||||
public WriteResult doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||
|
||||
maybeEmitEvent(new BeforeDeleteEvent<T>(queryObject, entityClass));
|
||||
maybeEmitEvent(new BeforeDeleteEvent<T>(queryObject, entityClass, collectionName));
|
||||
|
||||
DBObject dboq = queryMapper.getMappedObject(queryObject, entity);
|
||||
|
||||
@@ -1284,7 +1291,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
handleAnyWriteResultErrors(wr, dboq, MongoActionOperation.REMOVE);
|
||||
|
||||
maybeEmitEvent(new AfterDeleteEvent<T>(queryObject, entityClass));
|
||||
maybeEmitEvent(new AfterDeleteEvent<T>(queryObject, entityClass, collectionName));
|
||||
|
||||
return wr;
|
||||
}
|
||||
@@ -1292,13 +1299,12 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
|
||||
public <T> List<T> findAll(Class<T> entityClass) {
|
||||
return executeFindMultiInternal(new FindCallback(null), null, new ReadDbObjectCallback<T>(mongoConverter,
|
||||
entityClass), determineCollectionName(entityClass));
|
||||
return findAll(entityClass, determineCollectionName(entityClass));
|
||||
}
|
||||
|
||||
public <T> List<T> findAll(Class<T> entityClass, String collectionName) {
|
||||
return executeFindMultiInternal(new FindCallback(null), null, new ReadDbObjectCallback<T>(mongoConverter,
|
||||
entityClass), collectionName);
|
||||
entityClass, collectionName), collectionName);
|
||||
}
|
||||
|
||||
public <T> MapReduceResults<T> mapReduce(String inputCollectionName, String mapFunction, String reduceFunction,
|
||||
@@ -1343,7 +1349,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
|
||||
List<T> mappedResults = new ArrayList<T>();
|
||||
DbObjectCallback<T> callback = new ReadDbObjectCallback<T>(mongoConverter, entityClass);
|
||||
DbObjectCallback<T> callback = new ReadDbObjectCallback<T>(mongoConverter, entityClass, inputCollectionName);
|
||||
|
||||
for (DBObject dbObject : mapReduceOutput.results()) {
|
||||
mappedResults.add(callback.doWith(dbObject));
|
||||
@@ -1404,7 +1410,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
@SuppressWarnings("unchecked")
|
||||
Iterable<DBObject> resultSet = (Iterable<DBObject>) commandResult.get("retval");
|
||||
List<T> mappedResults = new ArrayList<T>();
|
||||
DbObjectCallback<T> callback = new ReadDbObjectCallback<T>(mongoConverter, entityClass);
|
||||
DbObjectCallback<T> callback = new ReadDbObjectCallback<T>(mongoConverter, entityClass, inputCollectionName);
|
||||
|
||||
for (DBObject dbObject : resultSet) {
|
||||
mappedResults.add(callback.doWith(dbObject));
|
||||
@@ -1506,7 +1512,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
CommandResult commandResult = executeCommand(command, this.readPreference);
|
||||
handleCommandError(commandResult, command);
|
||||
|
||||
return new AggregationResults<O>(returnPotentiallyMappedResults(outputType, commandResult), commandResult);
|
||||
return new AggregationResults<O>(returnPotentiallyMappedResults(outputType, commandResult, collectionName),
|
||||
commandResult);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1516,7 +1523,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
* @param commandResult
|
||||
* @return
|
||||
*/
|
||||
private <O> List<O> returnPotentiallyMappedResults(Class<O> outputType, CommandResult commandResult) {
|
||||
private <O> List<O> returnPotentiallyMappedResults(Class<O> outputType, CommandResult commandResult,
|
||||
String collectionName) {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Iterable<DBObject> resultSet = (Iterable<DBObject>) commandResult.get("result");
|
||||
@@ -1524,7 +1532,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
DbObjectCallback<O> callback = new UnwrapAndReadDbObjectCallback<O>(mongoConverter, outputType);
|
||||
DbObjectCallback<O> callback = new UnwrapAndReadDbObjectCallback<O>(mongoConverter, outputType, collectionName);
|
||||
|
||||
List<O> mappedResults = new ArrayList<O>();
|
||||
for (DBObject dbObject : resultSet) {
|
||||
@@ -1546,10 +1554,17 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
throw new InvalidDataAccessApiUsageException(String.format("Resource %s not found!", function));
|
||||
}
|
||||
|
||||
Scanner scanner = null;
|
||||
|
||||
try {
|
||||
return new Scanner(functionResource.getInputStream()).useDelimiter("\\A").next();
|
||||
scanner = new Scanner(functionResource.getInputStream());
|
||||
return scanner.useDelimiter("\\A").next();
|
||||
} catch (IOException e) {
|
||||
throw new InvalidDataAccessApiUsageException(String.format("Cannot read map-reduce file %s!", function), e);
|
||||
} finally {
|
||||
if (scanner != null) {
|
||||
scanner.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1564,8 +1579,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
throw new InvalidDataAccessApiUsageException(
|
||||
"Can not use skip or field specification with map reduce operations");
|
||||
}
|
||||
|
||||
if (query.getLimit() > 0) {
|
||||
if (query.getLimit() > 0 && mapReduceOptions.getLimit() == null) {
|
||||
mapReduceCommand.setLimit(query.getLimit());
|
||||
}
|
||||
if (query.getSortObject() != null) {
|
||||
@@ -1573,6 +1587,10 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
}
|
||||
|
||||
if (mapReduceOptions.getLimit() != null && mapReduceOptions.getLimit().intValue() > 0) {
|
||||
mapReduceCommand.setLimit(mapReduceOptions.getLimit());
|
||||
}
|
||||
|
||||
if (mapReduceOptions.getJavaScriptMode() != null) {
|
||||
mapReduceCommand.setJsMode(true);
|
||||
}
|
||||
@@ -1652,7 +1670,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
|
||||
return executeFindOneInternal(new FindOneCallback(mappedQuery, mappedFields), new ReadDbObjectCallback<T>(
|
||||
this.mongoConverter, entityClass), collectionName);
|
||||
this.mongoConverter, entityClass, collectionName), collectionName);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1667,7 +1685,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
*/
|
||||
protected <T> List<T> doFind(String collectionName, DBObject query, DBObject fields, Class<T> entityClass) {
|
||||
return doFind(collectionName, query, fields, entityClass, null, new ReadDbObjectCallback<T>(this.mongoConverter,
|
||||
entityClass));
|
||||
entityClass, collectionName));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1686,7 +1704,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
protected <T> List<T> doFind(String collectionName, DBObject query, DBObject fields, Class<T> entityClass,
|
||||
CursorPreparer preparer) {
|
||||
return doFind(collectionName, query, fields, entityClass, preparer, new ReadDbObjectCallback<T>(mongoConverter,
|
||||
entityClass));
|
||||
entityClass, collectionName));
|
||||
}
|
||||
|
||||
protected <S, T> List<T> doFind(String collectionName, DBObject query, DBObject fields, Class<S> entityClass,
|
||||
@@ -1742,7 +1760,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass);
|
||||
return executeFindOneInternal(new FindAndRemoveCallback(queryMapper.getMappedObject(query, entity), fields, sort),
|
||||
new ReadDbObjectCallback<T>(readerToUse, entityClass), collectionName);
|
||||
new ReadDbObjectCallback<T>(readerToUse, entityClass, collectionName), collectionName);
|
||||
}
|
||||
|
||||
protected <T> T doFindAndModify(String collectionName, DBObject query, DBObject fields, DBObject sort,
|
||||
@@ -1768,7 +1786,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
|
||||
return executeFindOneInternal(new FindAndModifyCallback(mappedQuery, fields, sort, mappedUpdate, options),
|
||||
new ReadDbObjectCallback<T>(readerToUse, entityClass), collectionName);
|
||||
new ReadDbObjectCallback<T>(readerToUse, entityClass, collectionName), collectionName);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1812,7 +1830,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
prepareCollection(collection);
|
||||
return collection;
|
||||
} catch (RuntimeException e) {
|
||||
throw potentiallyConvertRuntimeException(e);
|
||||
throw potentiallyConvertRuntimeException(e, exceptionTranslator);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1838,7 +1856,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
collectionName)));
|
||||
return result;
|
||||
} catch (RuntimeException e) {
|
||||
throw potentiallyConvertRuntimeException(e);
|
||||
throw potentiallyConvertRuntimeException(e, exceptionTranslator);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1891,7 +1909,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
throw potentiallyConvertRuntimeException(e);
|
||||
throw potentiallyConvertRuntimeException(e, exceptionTranslator);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1921,7 +1939,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
|
||||
} catch (RuntimeException e) {
|
||||
throw potentiallyConvertRuntimeException(e);
|
||||
throw potentiallyConvertRuntimeException(e, exceptionTranslator);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2000,18 +2018,6 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to convert the given {@link RuntimeException} into a {@link DataAccessException} but returns the original
|
||||
* exception if the conversation failed. Thus allows safe rethrowing of the return value.
|
||||
*
|
||||
* @param ex
|
||||
* @return
|
||||
*/
|
||||
private RuntimeException potentiallyConvertRuntimeException(RuntimeException ex) {
|
||||
RuntimeException resolved = this.exceptionTranslator.translateExceptionIfPossible(ex);
|
||||
return resolved == null ? ex : resolved;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inspects the given {@link CommandResult} for erros and potentially throws an
|
||||
* {@link InvalidDataAccessApiUsageException} for that error.
|
||||
@@ -2050,6 +2056,20 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
return queryMapper.getMappedSort(query.getSortObject(), mappingContext.getPersistentEntity(type));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to convert the given {@link RuntimeException} into a {@link DataAccessException} but returns the original
|
||||
* exception if the conversation failed. Thus allows safe re-throwing of the return value.
|
||||
*
|
||||
* @param ex the exception to translate
|
||||
* @param exceptionTranslator the {@link PersistenceExceptionTranslator} to be used for translation
|
||||
* @return
|
||||
*/
|
||||
private static RuntimeException potentiallyConvertRuntimeException(RuntimeException ex,
|
||||
PersistenceExceptionTranslator exceptionTranslator) {
|
||||
RuntimeException resolved = exceptionTranslator.translateExceptionIfPossible(ex);
|
||||
return resolved == null ? ex : resolved;
|
||||
}
|
||||
|
||||
// Callback implementations
|
||||
|
||||
/**
|
||||
@@ -2180,26 +2200,30 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
* {@link MongoReader}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
private class ReadDbObjectCallback<T> implements DbObjectCallback<T> {
|
||||
|
||||
private final EntityReader<? super T, DBObject> reader;
|
||||
private final Class<T> type;
|
||||
private final String collectionName;
|
||||
|
||||
public ReadDbObjectCallback(EntityReader<? super T, DBObject> reader, Class<T> type, String collectionName) {
|
||||
|
||||
public ReadDbObjectCallback(EntityReader<? super T, DBObject> reader, Class<T> type) {
|
||||
Assert.notNull(reader);
|
||||
Assert.notNull(type);
|
||||
this.reader = reader;
|
||||
this.type = type;
|
||||
this.collectionName = collectionName;
|
||||
}
|
||||
|
||||
public T doWith(DBObject object) {
|
||||
if (null != object) {
|
||||
maybeEmitEvent(new AfterLoadEvent<T>(object, type));
|
||||
maybeEmitEvent(new AfterLoadEvent<T>(object, type, collectionName));
|
||||
}
|
||||
T source = reader.read(type, object);
|
||||
if (null != source) {
|
||||
maybeEmitEvent(new AfterConvertEvent<T>(object, source));
|
||||
maybeEmitEvent(new AfterConvertEvent<T>(object, source, collectionName));
|
||||
}
|
||||
return source;
|
||||
}
|
||||
@@ -2207,8 +2231,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
class UnwrapAndReadDbObjectCallback<T> extends ReadDbObjectCallback<T> {
|
||||
|
||||
public UnwrapAndReadDbObjectCallback(EntityReader<? super T, DBObject> reader, Class<T> type) {
|
||||
super(reader, type);
|
||||
public UnwrapAndReadDbObjectCallback(EntityReader<? super T, DBObject> reader, Class<T> type, String collectionName) {
|
||||
super(reader, type, collectionName);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -2292,7 +2316,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
|
||||
} catch (RuntimeException e) {
|
||||
throw potentiallyConvertRuntimeException(e);
|
||||
throw potentiallyConvertRuntimeException(e, exceptionTranslator);
|
||||
}
|
||||
|
||||
return cursorToUse;
|
||||
@@ -2339,20 +2363,20 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
* @since 1.7
|
||||
* @author Thomas Darimont
|
||||
*/
|
||||
static class CloseableIterableCusorAdapter<T> implements CloseableIterator<T> {
|
||||
static class CloseableIterableCursorAdapter<T> implements CloseableIterator<T> {
|
||||
|
||||
private volatile Cursor cursor;
|
||||
private PersistenceExceptionTranslator exceptionTranslator;
|
||||
private DbObjectCallback<T> objectReadCallback;
|
||||
|
||||
/**
|
||||
* Creates a new {@link CloseableIterableCusorAdapter} backed by the given {@link Cursor}.
|
||||
* Creates a new {@link CloseableIterableCursorAdapter} backed by the given {@link Cursor}.
|
||||
*
|
||||
* @param cursor
|
||||
* @param exceptionTranslator
|
||||
* @param objectReadCallback
|
||||
*/
|
||||
public CloseableIterableCusorAdapter(Cursor cursor, PersistenceExceptionTranslator exceptionTranslator,
|
||||
public CloseableIterableCursorAdapter(Cursor cursor, PersistenceExceptionTranslator exceptionTranslator,
|
||||
DbObjectCallback<T> objectReadCallback) {
|
||||
|
||||
this.cursor = cursor;
|
||||
@@ -2370,7 +2394,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
try {
|
||||
return cursor.hasNext();
|
||||
} catch (RuntimeException ex) {
|
||||
throw exceptionTranslator.translateExceptionIfPossible(ex);
|
||||
throw potentiallyConvertRuntimeException(ex, exceptionTranslator);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2386,7 +2410,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
T converted = objectReadCallback.doWith(item);
|
||||
return converted;
|
||||
} catch (RuntimeException ex) {
|
||||
throw exceptionTranslator.translateExceptionIfPossible(ex);
|
||||
throw potentiallyConvertRuntimeException(ex, exceptionTranslator);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2397,7 +2421,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
try {
|
||||
c.close();
|
||||
} catch (RuntimeException ex) {
|
||||
throw exceptionTranslator.translateExceptionIfPossible(ex);
|
||||
throw potentiallyConvertRuntimeException(ex, exceptionTranslator);
|
||||
} finally {
|
||||
cursor = null;
|
||||
exceptionTranslator = null;
|
||||
|
||||
@@ -153,7 +153,7 @@ public class Aggregation {
|
||||
protected Aggregation(List<AggregationOperation> aggregationOperations, AggregationOptions options) {
|
||||
|
||||
Assert.notNull(aggregationOperations, "AggregationOperations must not be null!");
|
||||
Assert.isTrue(aggregationOperations.size() > 0, "At least one AggregationOperation has to be provided");
|
||||
Assert.isTrue(!aggregationOperations.isEmpty(), "At least one AggregationOperation has to be provided");
|
||||
Assert.notNull(options, "AggregationOptions must not be null!");
|
||||
|
||||
this.operations = aggregationOperations;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.springframework.data.mongodb.core.aggregation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
@@ -56,7 +57,7 @@ public enum AggregationFunctionExpressions {
|
||||
static class FunctionExpression implements AggregationExpression {
|
||||
|
||||
private final String name;
|
||||
private final Object[] values;
|
||||
private final List<Object> values;
|
||||
|
||||
/**
|
||||
* Creates a new {@link FunctionExpression} for the given name and values.
|
||||
@@ -70,7 +71,7 @@ public enum AggregationFunctionExpressions {
|
||||
Assert.notNull(values, "Values must not be null!");
|
||||
|
||||
this.name = name;
|
||||
this.values = values;
|
||||
this.values = Arrays.asList(values);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -80,10 +81,10 @@ public enum AggregationFunctionExpressions {
|
||||
@Override
|
||||
public DBObject toDbObject(AggregationOperationContext context) {
|
||||
|
||||
List<Object> args = new ArrayList<Object>(values.length);
|
||||
List<Object> args = new ArrayList<Object>(values.size());
|
||||
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
args.add(unpack(values[i], context));
|
||||
for (Object value : values) {
|
||||
args.add(unpack(value, context));
|
||||
}
|
||||
|
||||
return new BasicDBObject("$" + name, args);
|
||||
|
||||
@@ -75,15 +75,13 @@ public abstract class AbstractMongoConverter implements MongoConverter, Initiali
|
||||
*/
|
||||
private void initializeConverters() {
|
||||
|
||||
if (!conversionService.canConvert(ObjectId.class, String.class)) {
|
||||
conversionService.addConverter(ObjectIdToStringConverter.INSTANCE);
|
||||
}
|
||||
if (!conversionService.canConvert(String.class, ObjectId.class)) {
|
||||
conversionService.addConverter(StringToObjectIdConverter.INSTANCE);
|
||||
}
|
||||
conversionService.addConverter(ObjectIdToStringConverter.INSTANCE);
|
||||
conversionService.addConverter(StringToObjectIdConverter.INSTANCE);
|
||||
|
||||
if (!conversionService.canConvert(ObjectId.class, BigInteger.class)) {
|
||||
conversionService.addConverter(ObjectIdToBigIntegerConverter.INSTANCE);
|
||||
}
|
||||
|
||||
if (!conversionService.canConvert(BigInteger.class, ObjectId.class)) {
|
||||
conversionService.addConverter(BigIntegerToObjectIdConverter.INSTANCE);
|
||||
}
|
||||
|
||||
@@ -44,9 +44,9 @@ import org.springframework.data.convert.WritingConverter;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.BigDecimalToStringConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.BigIntegerToStringConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.NamedMongoScriptToDBObjectConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.DBObjectToNamedMongoScriptCoverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.DBObjectToStringConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.NamedMongoScriptToDBObjectConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.StringToBigDecimalConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.StringToBigIntegerConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.StringToURLConverter;
|
||||
@@ -192,8 +192,8 @@ public class CustomConversions {
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a conversion for the given converter. Inspects either generics or the {@link ConvertiblePair}s returned
|
||||
* by a {@link GenericConverter}.
|
||||
* Registers a conversion for the given converter. Inspects either generics of {@link Converter} and
|
||||
* {@link ConverterFactory} or the {@link ConvertiblePair}s returned by a {@link GenericConverter}.
|
||||
*
|
||||
* @param converter
|
||||
*/
|
||||
@@ -208,6 +208,10 @@ public class CustomConversions {
|
||||
for (ConvertiblePair pair : genericConverter.getConvertibleTypes()) {
|
||||
register(new ConverterRegistration(pair, isReading, isWriting));
|
||||
}
|
||||
} else if (converter instanceof ConverterFactory) {
|
||||
|
||||
Class<?>[] arguments = GenericTypeResolver.resolveTypeArguments(converter.getClass(), ConverterFactory.class);
|
||||
register(new ConverterRegistration(arguments[0], arguments[1], isReading, isWriting));
|
||||
} else if (converter instanceof Converter) {
|
||||
Class<?>[] arguments = GenericTypeResolver.resolveTypeArguments(converter.getClass(), Converter.class);
|
||||
register(new ConverterRegistration(arguments[0], arguments[1], isReading, isWriting));
|
||||
|
||||
@@ -75,9 +75,7 @@ class DBObjectAccessor {
|
||||
String part = parts.next();
|
||||
|
||||
if (parts.hasNext()) {
|
||||
BasicDBObject nestedDbObject = new BasicDBObject();
|
||||
dbObject.put(part, nestedDbObject);
|
||||
dbObject = nestedDbObject;
|
||||
dbObject = getOrCreateNestedDbObject(part, dbObject);
|
||||
} else {
|
||||
dbObject.put(part, value);
|
||||
}
|
||||
@@ -116,8 +114,14 @@ class DBObjectAccessor {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the given source object as map, i.e. {@link BasicDBObject}s and maps as is or {@literal null} otherwise.
|
||||
*
|
||||
* @param source can be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map<String, Object> getAsMap(Object source) {
|
||||
private static Map<String, Object> getAsMap(Object source) {
|
||||
|
||||
if (source instanceof BasicDBObject) {
|
||||
return (BasicDBObject) source;
|
||||
@@ -129,4 +133,26 @@ class DBObjectAccessor {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link DBObject} which either already exists in the given source under the given key, or creates a new
|
||||
* nested one, registers it with the source and returns it.
|
||||
*
|
||||
* @param key must not be {@literal null} or empty.
|
||||
* @param source must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
private static DBObject getOrCreateNestedDbObject(String key, DBObject source) {
|
||||
|
||||
Object existing = source.get(key);
|
||||
|
||||
if (existing instanceof BasicDBObject) {
|
||||
return (BasicDBObject) existing;
|
||||
}
|
||||
|
||||
DBObject nested = new BasicDBObject();
|
||||
source.put(key, nested);
|
||||
|
||||
return nested;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,9 +111,13 @@ abstract class GeoConverters {
|
||||
@Override
|
||||
public Point convert(DBObject source) {
|
||||
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Assert.isTrue(source.keySet().size() == 2, "Source must contain 2 elements");
|
||||
|
||||
return source == null ? null : new Point((Double) source.get("x"), (Double) source.get("y"));
|
||||
return new Point((Double) source.get("x"), (Double) source.get("y"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -264,7 +264,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
accessor.setProperty(idProperty, idValue);
|
||||
}
|
||||
|
||||
final ObjectPath currentPath = path.push(result, entity, idValue);
|
||||
final ObjectPath currentPath = path.push(result, entity,
|
||||
idValue != null ? dbo.get(idProperty.getFieldName()) : null);
|
||||
|
||||
// Set properties not already set in the constructor
|
||||
entity.doWithProperties(new PropertyHandler<MongoPersistentProperty>() {
|
||||
@@ -290,7 +291,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
final MongoPersistentProperty property = association.getInverse();
|
||||
Object value = dbo.get(property.getFieldName());
|
||||
|
||||
if (value == null) {
|
||||
if (value == null || entity.isConstructorArgument(property)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1197,10 +1198,6 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
|
||||
Object object = dbref == null ? null : path.getPathItem(dbref.getId(), dbref.getCollectionName());
|
||||
|
||||
if (object != null) {
|
||||
return (T) object;
|
||||
}
|
||||
|
||||
return (T) (object != null ? object : read(type, readRef(dbref), path));
|
||||
}
|
||||
|
||||
|
||||
@@ -867,7 +867,7 @@ public class QueryMapper {
|
||||
* @return
|
||||
*/
|
||||
protected Converter<MongoPersistentProperty, String> getPropertyConverter() {
|
||||
return PropertyToFieldNameConverter.INSTANCE;
|
||||
return new PositionParameterRetainingPropertyKeyConverter(name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -881,6 +881,28 @@ public class QueryMapper {
|
||||
return new AssociationConverter(getAssociation());
|
||||
}
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 1.8
|
||||
*/
|
||||
static class PositionParameterRetainingPropertyKeyConverter implements Converter<MongoPersistentProperty, String> {
|
||||
|
||||
private final KeyMapper keyMapper;
|
||||
|
||||
public PositionParameterRetainingPropertyKeyConverter(String rawKey) {
|
||||
this.keyMapper = new KeyMapper(rawKey);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public String convert(MongoPersistentProperty source) {
|
||||
return keyMapper.mapPropertyName(source);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.convert.QueryMapper.Field#getTypeHint()
|
||||
@@ -901,6 +923,61 @@ public class QueryMapper {
|
||||
|
||||
return NESTED_DOCUMENT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 1.8
|
||||
*/
|
||||
static class KeyMapper {
|
||||
|
||||
private final Iterator<String> iterator;
|
||||
|
||||
public KeyMapper(String key) {
|
||||
|
||||
this.iterator = Arrays.asList(key.split("\\.")).iterator();
|
||||
this.iterator.next();
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps the property name while retaining potential positional operator {@literal $}.
|
||||
*
|
||||
* @param property
|
||||
* @return
|
||||
*/
|
||||
protected String mapPropertyName(MongoPersistentProperty property) {
|
||||
|
||||
StringBuilder mappedName = new StringBuilder(PropertyToFieldNameConverter.INSTANCE.convert(property));
|
||||
boolean inspect = iterator.hasNext();
|
||||
|
||||
while (inspect) {
|
||||
|
||||
String partial = iterator.next();
|
||||
boolean isPositional = (isPositionalParameter(partial) && (property.isMap() || property.isCollectionLike()));
|
||||
|
||||
if (isPositional) {
|
||||
mappedName.append(".").append(partial);
|
||||
}
|
||||
|
||||
inspect = isPositional && iterator.hasNext();
|
||||
}
|
||||
|
||||
return mappedName.toString();
|
||||
}
|
||||
|
||||
private static boolean isPositionalParameter(String partial) {
|
||||
|
||||
if ("$".equals(partial)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
Long.valueOf(partial);
|
||||
return true;
|
||||
} catch (NumberFormatException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
@@ -24,13 +22,11 @@ import org.springframework.data.mapping.Association;
|
||||
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.core.mapping.MongoPersistentProperty.PropertyToFieldNameConverter;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.data.mongodb.core.query.Update.Modifier;
|
||||
import org.springframework.data.mongodb.core.query.Update.Modifiers;
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DBObject;
|
||||
@@ -213,7 +209,7 @@ public class UpdateMapper extends QueryMapper {
|
||||
*/
|
||||
@Override
|
||||
protected Converter<MongoPersistentProperty, String> getPropertyConverter() {
|
||||
return new UpdatePropertyConverter(key);
|
||||
return new PositionParameterRetainingPropertyKeyConverter(key);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -225,99 +221,6 @@ public class UpdateMapper extends QueryMapper {
|
||||
return new UpdateAssociationConverter(getAssociation(), key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Special mapper handling positional parameter {@literal $} within property names.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @since 1.7
|
||||
*/
|
||||
private static class UpdateKeyMapper {
|
||||
|
||||
private final Iterator<String> iterator;
|
||||
|
||||
protected UpdateKeyMapper(String rawKey) {
|
||||
|
||||
Assert.hasText(rawKey, "Key must not be null or empty!");
|
||||
|
||||
this.iterator = Arrays.asList(rawKey.split("\\.")).iterator();
|
||||
this.iterator.next();
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps the property name while retaining potential positional operator {@literal $}.
|
||||
*
|
||||
* @param property
|
||||
* @return
|
||||
*/
|
||||
protected String mapPropertyName(MongoPersistentProperty property) {
|
||||
|
||||
String mappedName = PropertyToFieldNameConverter.INSTANCE.convert(property);
|
||||
|
||||
boolean inspect = iterator.hasNext();
|
||||
while (inspect) {
|
||||
|
||||
String partial = iterator.next();
|
||||
|
||||
boolean isPositional = isPositionalParameter(partial);
|
||||
if (isPositional) {
|
||||
mappedName += "." + partial;
|
||||
}
|
||||
|
||||
inspect = isPositional && iterator.hasNext();
|
||||
}
|
||||
|
||||
return mappedName;
|
||||
}
|
||||
|
||||
boolean isPositionalParameter(String partial) {
|
||||
|
||||
if (partial.equals("$")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
Long.valueOf(partial);
|
||||
return true;
|
||||
} catch (NumberFormatException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Special {@link Converter} for {@link MongoPersistentProperty} instances that will concatenate the {@literal $}
|
||||
* contained in the source update key.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
private static class UpdatePropertyConverter implements Converter<MongoPersistentProperty, String> {
|
||||
|
||||
private final UpdateKeyMapper mapper;
|
||||
|
||||
/**
|
||||
* Creates a new {@link UpdatePropertyConverter} with the given update key.
|
||||
*
|
||||
* @param updateKey must not be {@literal null} or empty.
|
||||
*/
|
||||
public UpdatePropertyConverter(String updateKey) {
|
||||
|
||||
Assert.hasText(updateKey, "Update key must not be null or empty!");
|
||||
|
||||
this.mapper = new UpdateKeyMapper(updateKey);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public String convert(MongoPersistentProperty property) {
|
||||
return mapper.mapPropertyName(property);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Converter} retaining positional parameter {@literal $} for {@link Association}s.
|
||||
*
|
||||
@@ -325,7 +228,7 @@ public class UpdateMapper extends QueryMapper {
|
||||
*/
|
||||
protected static class UpdateAssociationConverter extends AssociationConverter {
|
||||
|
||||
private final UpdateKeyMapper mapper;
|
||||
private final KeyMapper mapper;
|
||||
|
||||
/**
|
||||
* Creates a new {@link AssociationConverter} for the given {@link Association}.
|
||||
@@ -335,7 +238,7 @@ public class UpdateMapper extends QueryMapper {
|
||||
public UpdateAssociationConverter(Association<MongoPersistentProperty> association, String key) {
|
||||
|
||||
super(association);
|
||||
this.mapper = new UpdateKeyMapper(key);
|
||||
this.mapper = new KeyMapper(key);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 the original author or authors.
|
||||
* Copyright 2010-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,6 +17,7 @@ package org.springframework.data.mongodb.core.index;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.springframework.data.domain.Sort.Direction;
|
||||
@@ -44,7 +45,7 @@ public class Index implements IndexDefinition {
|
||||
*
|
||||
* @deprecated since 1.7.
|
||||
*/
|
||||
@Deprecated//
|
||||
@Deprecated //
|
||||
DROP
|
||||
}
|
||||
|
||||
@@ -175,11 +176,18 @@ public class Index implements IndexDefinition {
|
||||
return unique();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.index.IndexDefinition#getIndexKeys()
|
||||
*/
|
||||
public DBObject getIndexKeys() {
|
||||
|
||||
DBObject dbo = new BasicDBObject();
|
||||
for (String k : fieldSpec.keySet()) {
|
||||
dbo.put(k, fieldSpec.get(k).equals(Direction.ASC) ? 1 : -1);
|
||||
|
||||
for (Entry<String, Direction> entry : fieldSpec.entrySet()) {
|
||||
dbo.put(entry.getKey(), Direction.ASC.equals(entry.getValue()) ? 1 : -1);
|
||||
}
|
||||
|
||||
return dbo;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,10 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.mapping.Association;
|
||||
import org.springframework.data.mapping.AssociationHandler;
|
||||
import org.springframework.data.mapping.PropertyHandler;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.mongodb.core.index.Index.Duplicates;
|
||||
import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexResolver.TextIndexIncludeOptions.IncludeStrategy;
|
||||
import org.springframework.data.mongodb.core.index.TextIndexDefinition.TextIndexDefinitionBuilder;
|
||||
@@ -123,6 +126,8 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
||||
}
|
||||
});
|
||||
|
||||
indexInformation.addAll(resolveIndexesForDbrefs("", root.getCollection(), root));
|
||||
|
||||
return indexInformation;
|
||||
}
|
||||
|
||||
@@ -168,6 +173,8 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
||||
}
|
||||
});
|
||||
|
||||
indexInformation.addAll(resolveIndexesForDbrefs(path, collection, entity));
|
||||
|
||||
return indexInformation;
|
||||
}
|
||||
|
||||
@@ -193,18 +200,19 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
||||
return createCompoundIndexDefinitions(dotPath, collection, entity);
|
||||
}
|
||||
|
||||
private Collection<? extends IndexDefinitionHolder> potentiallyCreateTextIndexDefinition(MongoPersistentEntity<?> root) {
|
||||
private Collection<? extends IndexDefinitionHolder> potentiallyCreateTextIndexDefinition(
|
||||
MongoPersistentEntity<?> root) {
|
||||
|
||||
TextIndexDefinitionBuilder indexDefinitionBuilder = new TextIndexDefinitionBuilder().named(root.getType()
|
||||
.getSimpleName() + "_TextIndex");
|
||||
TextIndexDefinitionBuilder indexDefinitionBuilder = new TextIndexDefinitionBuilder()
|
||||
.named(root.getType().getSimpleName() + "_TextIndex");
|
||||
|
||||
if (StringUtils.hasText(root.getLanguage())) {
|
||||
indexDefinitionBuilder.withDefaultLanguage(root.getLanguage());
|
||||
}
|
||||
|
||||
try {
|
||||
appendTextIndexInformation("", indexDefinitionBuilder, root,
|
||||
new TextIndexIncludeOptions(IncludeStrategy.DEFAULT), new CycleGuard());
|
||||
appendTextIndexInformation("", indexDefinitionBuilder, root, new TextIndexIncludeOptions(IncludeStrategy.DEFAULT),
|
||||
new CycleGuard());
|
||||
} catch (CyclicPropertyReferenceException e) {
|
||||
LOGGER.info(e.getMessage());
|
||||
}
|
||||
@@ -220,9 +228,8 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
||||
|
||||
}
|
||||
|
||||
private void appendTextIndexInformation(final String dotPath,
|
||||
final TextIndexDefinitionBuilder indexDefinitionBuilder, final MongoPersistentEntity<?> entity,
|
||||
final TextIndexIncludeOptions includeOptions, final CycleGuard guard) {
|
||||
private void appendTextIndexInformation(final String dotPath, final TextIndexDefinitionBuilder indexDefinitionBuilder,
|
||||
final MongoPersistentEntity<?> entity, final TextIndexIncludeOptions includeOptions, final CycleGuard guard) {
|
||||
|
||||
entity.doWithProperties(new PropertyHandler<MongoPersistentProperty>() {
|
||||
|
||||
@@ -249,8 +256,8 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
||||
|
||||
TextIndexIncludeOptions optionsForNestedType = includeOptions;
|
||||
if (!IncludeStrategy.FORCE.equals(includeOptions.getStrategy()) && indexed != null) {
|
||||
optionsForNestedType = new TextIndexIncludeOptions(IncludeStrategy.FORCE, new TextIndexedFieldSpec(
|
||||
propertyDotPath, weight));
|
||||
optionsForNestedType = new TextIndexIncludeOptions(IncludeStrategy.FORCE,
|
||||
new TextIndexedFieldSpec(propertyDotPath, weight));
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -259,9 +266,8 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
||||
} catch (CyclicPropertyReferenceException e) {
|
||||
LOGGER.info(e.getMessage(), e);
|
||||
} catch (InvalidDataAccessApiUsageException e) {
|
||||
LOGGER.info(
|
||||
String.format("Potentially invalid index structure discovered. Breaking operation for %s.",
|
||||
entity.getName()), e);
|
||||
LOGGER.info(String.format("Potentially invalid index structure discovered. Breaking operation for %s.",
|
||||
entity.getName()), e);
|
||||
}
|
||||
} else if (includeOptions.isForce() || indexed != null) {
|
||||
indexDefinitionBuilder.onField(propertyDotPath, weight);
|
||||
@@ -306,8 +312,8 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
||||
protected IndexDefinitionHolder createCompoundIndexDefinition(String dotPath, String fallbackCollection,
|
||||
CompoundIndex index, MongoPersistentEntity<?> entity) {
|
||||
|
||||
CompoundIndexDefinition indexDefinition = new CompoundIndexDefinition(resolveCompoundIndexKeyFromStringDefinition(
|
||||
dotPath, index.def()));
|
||||
CompoundIndexDefinition indexDefinition = new CompoundIndexDefinition(
|
||||
resolveCompoundIndexKeyFromStringDefinition(dotPath, index.def()));
|
||||
|
||||
if (!index.useGeneratedName()) {
|
||||
indexDefinition.named(pathAwareIndexName(index.name(), dotPath, null));
|
||||
@@ -431,13 +437,45 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
||||
|
||||
if (StringUtils.hasText(dotPath)) {
|
||||
|
||||
nameToUse = StringUtils.hasText(nameToUse) ? (property != null ? dotPath.replace("." + property.getFieldName(),
|
||||
"") : dotPath) + "." + nameToUse : dotPath;
|
||||
nameToUse = StringUtils.hasText(nameToUse)
|
||||
? (property != null ? dotPath.replace("." + property.getFieldName(), "") : dotPath) + "." + nameToUse
|
||||
: dotPath;
|
||||
}
|
||||
return nameToUse;
|
||||
|
||||
}
|
||||
|
||||
private List<IndexDefinitionHolder> resolveIndexesForDbrefs(final String path, final String collection,
|
||||
MongoPersistentEntity<?> entity) {
|
||||
|
||||
final List<IndexDefinitionHolder> indexes = new ArrayList<IndexDefinitionHolder>(0);
|
||||
entity.doWithAssociations(new AssociationHandler<MongoPersistentProperty>() {
|
||||
|
||||
@Override
|
||||
public void doWithAssociation(Association<MongoPersistentProperty> association) {
|
||||
|
||||
MongoPersistentProperty property = association.getInverse();
|
||||
|
||||
String propertyDotPath = (StringUtils.hasText(path) ? path + "." : "") + property.getFieldName();
|
||||
|
||||
if (property.isAnnotationPresent(GeoSpatialIndexed.class) || property.isAnnotationPresent(TextIndexed.class)) {
|
||||
throw new MappingException(
|
||||
String.format("Cannot create geospatial-/text- index on DBRef in collection '%s' for path '%s'.",
|
||||
collection, propertyDotPath));
|
||||
}
|
||||
|
||||
IndexDefinitionHolder indexDefinitionHolder = createIndexDefinitionHolderForProperty(propertyDotPath,
|
||||
collection, property);
|
||||
|
||||
if (indexDefinitionHolder != null) {
|
||||
indexes.add(indexDefinitionHolder);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return indexes;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link CycleGuard} holds information about properties and the paths for accessing those. This information is used
|
||||
* to detect potential cycles within the references.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013 by the original author(s).
|
||||
* Copyright 2013-2015 by the original author(s).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,6 +21,7 @@ import com.mongodb.DBObject;
|
||||
* Base class for delete events.
|
||||
*
|
||||
* @author Martin Baumgartner
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public abstract class AbstractDeleteEvent<T> extends MongoMappingEvent<DBObject> {
|
||||
|
||||
@@ -31,11 +32,25 @@ public abstract class AbstractDeleteEvent<T> extends MongoMappingEvent<DBObject>
|
||||
* Creates a new {@link AbstractDeleteEvent} for the given {@link DBObject} and type.
|
||||
*
|
||||
* @param dbo must not be {@literal null}.
|
||||
* @param type , possibly be {@literal null}.
|
||||
* @param type can be {@literal null}.
|
||||
* @deprecated since 1.8. Please use {@link #AbstractDeleteEvent(DBObject, Class, String)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public AbstractDeleteEvent(DBObject dbo, Class<T> type) {
|
||||
this(dbo, type, null);
|
||||
}
|
||||
|
||||
super(dbo, dbo);
|
||||
/**
|
||||
* Creates a new {@link AbstractDeleteEvent} for the given {@link DBObject} and type.
|
||||
*
|
||||
* @param dbo must not be {@literal null}.
|
||||
* @param type can be {@literal null}.
|
||||
* @param collectionName can be {@literal null}.
|
||||
* @since 1.8
|
||||
*/
|
||||
public AbstractDeleteEvent(DBObject dbo, Class<T> type, String collectionName) {
|
||||
|
||||
super(dbo, dbo, collectionName);
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2013 by the original author(s).
|
||||
* Copyright 2011-2015 by the original author(s).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -28,6 +28,7 @@ import com.mongodb.DBObject;
|
||||
* @author Jon Brisbin
|
||||
* @author Oliver Gierke
|
||||
* @author Martin Baumgartner
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public abstract class AbstractMongoEventListener<E> implements ApplicationListener<MongoMappingEvent<?>> {
|
||||
|
||||
@@ -46,14 +47,14 @@ public abstract class AbstractMongoEventListener<E> implements ApplicationListen
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public void onApplicationEvent(MongoMappingEvent<?> event) {
|
||||
|
||||
if (event instanceof AfterLoadEvent) {
|
||||
AfterLoadEvent<?> afterLoadEvent = (AfterLoadEvent<?>) event;
|
||||
|
||||
if (domainClass.isAssignableFrom(afterLoadEvent.getType())) {
|
||||
onAfterLoad(event.getDBObject());
|
||||
onAfterLoad((AfterLoadEvent<E>) event);
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -65,18 +66,18 @@ public abstract class AbstractMongoEventListener<E> implements ApplicationListen
|
||||
|
||||
if (eventDomainType != null && domainClass.isAssignableFrom(eventDomainType)) {
|
||||
if (event instanceof BeforeDeleteEvent) {
|
||||
onBeforeDelete(event.getDBObject());
|
||||
onBeforeDelete((BeforeDeleteEvent<E>) event);
|
||||
}
|
||||
if (event instanceof AfterDeleteEvent) {
|
||||
onAfterDelete(event.getDBObject());
|
||||
onAfterDelete((AfterDeleteEvent<E>) event);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
E source = (E) event.getSource();
|
||||
Object source = event.getSource();
|
||||
|
||||
// Check for matching domain type and invoke callbacks
|
||||
if (source != null && !domainClass.isAssignableFrom(source.getClass())) {
|
||||
@@ -84,55 +85,185 @@ public abstract class AbstractMongoEventListener<E> implements ApplicationListen
|
||||
}
|
||||
|
||||
if (event instanceof BeforeConvertEvent) {
|
||||
onBeforeConvert(source);
|
||||
onBeforeConvert((BeforeConvertEvent<E>) event);
|
||||
} else if (event instanceof BeforeSaveEvent) {
|
||||
onBeforeSave(source, event.getDBObject());
|
||||
onBeforeSave((BeforeSaveEvent<E>) event);
|
||||
} else if (event instanceof AfterSaveEvent) {
|
||||
onAfterSave(source, event.getDBObject());
|
||||
onAfterSave((AfterSaveEvent<E>) event);
|
||||
} else if (event instanceof AfterConvertEvent) {
|
||||
onAfterConvert(event.getDBObject(), source);
|
||||
onAfterConvert((AfterConvertEvent<E>) event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures source element before conversion.
|
||||
*
|
||||
* @param source will never be {@literal null}.
|
||||
* @deprecated since 1.8. Please use {@link #onBeforeConvert(BeforeConvertEvent)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public void onBeforeConvert(E source) {
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("onBeforeConvert({})", source);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures {@link BeforeConvertEvent}.
|
||||
*
|
||||
* @param event never {@literal null}.
|
||||
* @since 1.8
|
||||
*/
|
||||
public void onBeforeConvert(BeforeConvertEvent<E> event) {
|
||||
onBeforeConvert(event.getSource());
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures source element and {@link com.mongodb.DBObject} representation before save.
|
||||
*
|
||||
* @param source will never be {@literal null}.
|
||||
* @param dbo can be {@literal null}.
|
||||
* @deprecated since 1.8. Please use {@link #onBeforeSave(BeforeSaveEvent)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public void onBeforeSave(E source, DBObject dbo) {
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("onBeforeSave({}, {})", source, dbo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures {@link BeforeSaveEvent}.
|
||||
*
|
||||
* @param event will never be {@literal null}.
|
||||
* @since 1.8
|
||||
*/
|
||||
public void onBeforeSave(BeforeSaveEvent<E> event) {
|
||||
onBeforeSave(event.getSource(), event.getDBObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures source element and {@link com.mongodb.DBObject} representation after save.
|
||||
*
|
||||
* @param source will never be {@literal null}.
|
||||
* @param dbo can be {@literal null}.
|
||||
* @deprecated since 1.8. Please use {@link #onAfterSave(AfterSaveEvent)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public void onAfterSave(E source, DBObject dbo) {
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("onAfterSave({}, {})", source, dbo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures {@link AfterSaveEvent}.
|
||||
*
|
||||
* @param event will never be {@literal null}.
|
||||
* @since 1.8
|
||||
*/
|
||||
public void onAfterSave(AfterSaveEvent<E> event) {
|
||||
onAfterSave(event.getSource(), event.getDBObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures raw {@link com.mongodb.DBObject} when read from MongoDB.
|
||||
*
|
||||
* @param dbo can be {@literal null}.
|
||||
* @deprecated since 1.8. Please use {@link #onAfterLoad(AfterLoadEvent)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public void onAfterLoad(DBObject dbo) {
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("onAfterLoad({})", dbo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures {@link AfterLoadEvent}.
|
||||
*
|
||||
* @param event will never be {@literal null}.
|
||||
* @since 1.8
|
||||
*/
|
||||
public void onAfterLoad(AfterLoadEvent<E> event) {
|
||||
onAfterLoad(event.getDBObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures raw {@link com.mongodb.DBObject} and converted domain type after conversion.
|
||||
*
|
||||
* @param dbo can be {@literal null}.
|
||||
* @param source will never be {@literal null}.
|
||||
* @deprecated since 1.8. Please use {@link #onAfterConvert(AfterConvertEvent)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public void onAfterConvert(DBObject dbo, E source) {
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("onAfterConvert({}, {})", dbo, source);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures {@link AfterConvertEvent}.
|
||||
*
|
||||
* @param event will never be {@literal null}.
|
||||
* @since 1.8
|
||||
*/
|
||||
public void onAfterConvert(AfterConvertEvent<E> event) {
|
||||
onAfterConvert(event.getDBObject(), event.getSource());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures {@link com.mongodb.DBObject} after delete.
|
||||
*
|
||||
* @param dbo can be {@literal null}.
|
||||
* @deprecated since 1.8. Please use {@link #onAfterDelete(AfterDeleteEvent)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public void onAfterDelete(DBObject dbo) {
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("onAfterDelete({})", dbo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures {@link AfterDeleteEvent}.
|
||||
*
|
||||
* @param event will never be {@literal null}.
|
||||
* @since 1.8
|
||||
*/
|
||||
public void onAfterDelete(AfterDeleteEvent<E> event) {
|
||||
onAfterDelete(event.getDBObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Capture {@link com.mongodb.DBObject} before delete.
|
||||
*
|
||||
* @param dbo can be {@literal null}.
|
||||
* @deprecated since 1.8. Please use {@link #onBeforeDelete(BeforeDeleteEvent)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public void onBeforeDelete(DBObject dbo) {
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("onBeforeDelete({})", dbo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Capture {@link BeforeDeleteEvent}.
|
||||
*
|
||||
* @param event will never be {@literal null}.
|
||||
* @since 1.8
|
||||
*/
|
||||
public void onBeforeDelete(BeforeDeleteEvent<E> event) {
|
||||
onBeforeDelete(event.getDBObject());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011 by the original author(s).
|
||||
* Copyright (c) 2011-2015 by the original author(s).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -13,20 +13,42 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.mongodb.core.mapping.event;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* {@link MongoMappingEvent} thrown after convert of a document.
|
||||
*
|
||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class AfterConvertEvent<E> extends MongoMappingEvent<E> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Creates new {@link AfterConvertEvent}.
|
||||
*
|
||||
* @param dbo can be {@literal null}.
|
||||
* @param source must not be {@literal null}.
|
||||
* @deprecated since 1.8. Please use {@link #AfterConvertEvent(DBObject, Object, String)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public AfterConvertEvent(DBObject dbo, E source) {
|
||||
super(source, dbo);
|
||||
this(dbo, source, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new {@link AfterConvertEvent}.
|
||||
*
|
||||
* @param dbo can be {@literal null}.
|
||||
* @param source must not be {@literal null}.
|
||||
* @param collectionName can be {@literal null}.
|
||||
* @since 1.8
|
||||
*/
|
||||
public AfterConvertEvent(DBObject dbo, E source, String collectionName) {
|
||||
super(source, dbo, collectionName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013 by the original author(s).
|
||||
* Copyright 2013-2015 by the original author(s).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,6 +22,7 @@ import com.mongodb.DBObject;
|
||||
* will be the query document <em>after</am> it has been mapped onto the domain type handled.
|
||||
*
|
||||
* @author Martin Baumgartner
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class AfterDeleteEvent<T> extends AbstractDeleteEvent<T> {
|
||||
|
||||
@@ -32,8 +33,22 @@ public class AfterDeleteEvent<T> extends AbstractDeleteEvent<T> {
|
||||
*
|
||||
* @param dbo must not be {@literal null}.
|
||||
* @param type can be {@literal null}.
|
||||
* @deprecated since 1.8. Please use {@link #AfterDeleteEvent(DBObject, Class, String)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public AfterDeleteEvent(DBObject dbo, Class<T> type) {
|
||||
super(dbo, type);
|
||||
this(dbo, type, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link AfterDeleteEvent} for the given {@link DBObject}, type and collectionName.
|
||||
*
|
||||
* @param dbo must not be {@literal null}.
|
||||
* @param type can be {@literal null}.
|
||||
* @param collectionName can be {@literal null}.
|
||||
* @since 1.8
|
||||
*/
|
||||
public AfterDeleteEvent(DBObject dbo, Class<T> type, String collectionName) {
|
||||
super(dbo, type, collectionName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011 by the original author(s).
|
||||
* Copyright (c) 2011-2015 by the original author(s).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -26,6 +26,7 @@ import com.mongodb.DBObject;
|
||||
* @author Oliver Gierke
|
||||
* @author Jon Brisbin
|
||||
* @author Christoph Leiter
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class AfterLoadEvent<T> extends MongoMappingEvent<DBObject> {
|
||||
|
||||
@@ -36,11 +37,25 @@ public class AfterLoadEvent<T> extends MongoMappingEvent<DBObject> {
|
||||
* Creates a new {@link AfterLoadEvent} for the given {@link DBObject} and type.
|
||||
*
|
||||
* @param dbo must not be {@literal null}.
|
||||
* @param type must not be {@literal null}.
|
||||
* @param type can be {@literal null}.
|
||||
* @deprecated since 1.8. Please use {@link #AfterLoadEvent(DBObject, Class, String)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public AfterLoadEvent(DBObject dbo, Class<T> type) {
|
||||
this(dbo, type, null);
|
||||
}
|
||||
|
||||
super(dbo, dbo);
|
||||
/**
|
||||
* Creates a new {@link AfterLoadEvent} for the given {@link DBObject}, type and collectionName.
|
||||
*
|
||||
* @param dbo must not be {@literal null}.
|
||||
* @param type must not be {@literal null}.
|
||||
* @param collectionName can be {@literal null}.
|
||||
* @since 1.8
|
||||
*/
|
||||
public AfterLoadEvent(DBObject dbo, Class<T> type, String collectionName) {
|
||||
|
||||
super(dbo, dbo, collectionName);
|
||||
|
||||
Assert.notNull(type, "Type must not be null!");
|
||||
this.type = type;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011 by the original author(s).
|
||||
* Copyright (c) 2011-2015 by the original author(s).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,14 +19,37 @@ package org.springframework.data.mongodb.core.mapping.event;
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* {@link MongoMappingEvent} triggered after save of a document.
|
||||
*
|
||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class AfterSaveEvent<E> extends MongoMappingEvent<E> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Creates new {@link AfterSaveEvent}
|
||||
*
|
||||
* @param source must not be {@literal null}.
|
||||
* @param dbo can be {@literal null}.
|
||||
* @deprecated since 1.8. Please use {@link #AfterSaveEvent(Object, DBObject, String)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public AfterSaveEvent(E source, DBObject dbo) {
|
||||
super(source, dbo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new {@link AfterSaveEvent}.
|
||||
*
|
||||
* @param source must not be {@literal null}.
|
||||
* @param dbo can be {@literal null}.
|
||||
* @param collectionName can be {@literal null}.
|
||||
* @since 1.8
|
||||
*/
|
||||
public AfterSaveEvent(E source, DBObject dbo, String collectionName) {
|
||||
super(source, dbo, collectionName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
* Copyright 2011-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,12 +20,31 @@ package org.springframework.data.mongodb.core.mapping.event;
|
||||
*
|
||||
* @author Jon Brisbin
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class BeforeConvertEvent<T> extends MongoMappingEvent<T> {
|
||||
|
||||
private static final long serialVersionUID = 252614269008845243L;
|
||||
|
||||
/**
|
||||
* Creates new {@link BeforeConvertEvent}.
|
||||
*
|
||||
* @param source must not be {@literal null}.
|
||||
* @deprecated since 1.8. Please use {@link #BeforeConvertEvent(Object, String)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public BeforeConvertEvent(T source) {
|
||||
super(source, null);
|
||||
this(source, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new {@link BeforeConvertEvent}.
|
||||
*
|
||||
* @param source must not be {@literal null}.
|
||||
* @param collectionName can be {@literal null}.
|
||||
* @since 1.8
|
||||
*/
|
||||
public BeforeConvertEvent(T source, String collectionName) {
|
||||
super(source, null, collectionName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013 by the original author(s).
|
||||
* Copyright 2013-2015 by the original author(s).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,6 +22,7 @@ import com.mongodb.DBObject;
|
||||
* document <em>before</em> being mapped based on the domain class handled.
|
||||
*
|
||||
* @author Martin Baumgartner
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class BeforeDeleteEvent<T> extends AbstractDeleteEvent<T> {
|
||||
|
||||
@@ -32,8 +33,22 @@ public class BeforeDeleteEvent<T> extends AbstractDeleteEvent<T> {
|
||||
*
|
||||
* @param dbo must not be {@literal null}.
|
||||
* @param type can be {@literal null}.
|
||||
* @deprecated since 1.8. Please use {@link #BeforeDeleteEvent(DBObject, Class, String)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public BeforeDeleteEvent(DBObject dbo, Class<T> type) {
|
||||
super(dbo, type);
|
||||
this(dbo, type, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link BeforeDeleteEvent} for the given {@link DBObject}, type and collectionName.
|
||||
*
|
||||
* @param dbo must not be {@literal null}.
|
||||
* @param type can be {@literal null}.
|
||||
* @param collectionName can be {@literal null}.
|
||||
* @since 1.8
|
||||
*/
|
||||
public BeforeDeleteEvent(DBObject dbo, Class<T> type, String collectionName) {
|
||||
super(dbo, type, collectionName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011 by the original author(s).
|
||||
* Copyright (c) 2011-2015 by the original author(s).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,14 +19,37 @@ package org.springframework.data.mongodb.core.mapping.event;
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* {@link MongoMappingEvent} triggered before save of a document.
|
||||
*
|
||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class BeforeSaveEvent<E> extends MongoMappingEvent<E> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Creates new {@link BeforeSaveEvent}.
|
||||
*
|
||||
* @param source must not be {@literal null}.
|
||||
* @param dbo can be {@literal null}.
|
||||
* @deprecated since 1.8. Please use {@link #BeforeSaveEvent(Object, DBObject, String)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public BeforeSaveEvent(E source, DBObject dbo) {
|
||||
super(source, dbo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new {@link BeforeSaveEvent}.
|
||||
*
|
||||
* @param source must not be {@literal null}.
|
||||
* @param dbo can be {@literal null}.
|
||||
* @param collectionName can be {@literal null}.
|
||||
* @since 1.8
|
||||
*/
|
||||
public BeforeSaveEvent(E source, DBObject dbo, String collectionName) {
|
||||
super(source, dbo, collectionName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011 by the original author(s).
|
||||
* Copyright (c) 2011-2015 by the original author(s).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,26 +16,69 @@
|
||||
|
||||
package org.springframework.data.mongodb.core.mapping.event;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* Base {@link ApplicationEvent} triggered by Spring Data MongoDB.
|
||||
*
|
||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class MongoMappingEvent<T> extends ApplicationEvent {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final DBObject dbo;
|
||||
private final String collectionName;
|
||||
|
||||
/**
|
||||
* Creates new {@link MongoMappingEvent}.
|
||||
*
|
||||
* @param source must not be {@literal null}.
|
||||
* @param dbo can be {@literal null}.
|
||||
* @deprecated since 1.8. Please use {@link #MongoMappingEvent(Object, DBObject, String)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public MongoMappingEvent(T source, DBObject dbo) {
|
||||
super(source);
|
||||
this.dbo = dbo;
|
||||
this(source, dbo, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new {@link MongoMappingEvent}.
|
||||
*
|
||||
* @param source must not be {@literal null}.
|
||||
* @param dbo can be {@literal null}.
|
||||
* @param collectionName can be {@literal null}.
|
||||
*/
|
||||
public MongoMappingEvent(T source, DBObject dbo, String collectionName) {
|
||||
|
||||
super(source);
|
||||
this.dbo = dbo;
|
||||
this.collectionName = collectionName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@literal null} if not set.
|
||||
*/
|
||||
public DBObject getDBObject() {
|
||||
return dbo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the collection the event refers to.
|
||||
*
|
||||
* @return {@literal null} if not set.
|
||||
* @since 1.8
|
||||
*/
|
||||
public String getCollectionName() {
|
||||
return collectionName;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.EventObject#getSource()
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
@Override
|
||||
public T getSource() {
|
||||
|
||||
@@ -45,6 +45,8 @@ public class MapReduceOptions {
|
||||
|
||||
private Boolean verbose = true;
|
||||
|
||||
private Integer limit;
|
||||
|
||||
private Map<String, Object> extraOptions = new HashMap<String, Object>();
|
||||
|
||||
/**
|
||||
@@ -64,6 +66,8 @@ public class MapReduceOptions {
|
||||
* @return MapReduceOptions so that methods can be chained in a fluent API style
|
||||
*/
|
||||
public MapReduceOptions limit(int limit) {
|
||||
|
||||
this.limit = limit;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -247,6 +251,15 @@ public class MapReduceOptions {
|
||||
return this.scopeVariables;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the maximum number of documents for the input into the map function.
|
||||
*
|
||||
* @return {@literal null} if not set.
|
||||
*/
|
||||
public Integer getLimit() {
|
||||
return limit;
|
||||
}
|
||||
|
||||
public DBObject getOptionsObject() {
|
||||
BasicDBObject cmd = new BasicDBObject();
|
||||
|
||||
@@ -264,6 +277,10 @@ public class MapReduceOptions {
|
||||
cmd.put("scope", scopeVariables);
|
||||
}
|
||||
|
||||
if (limit != null) {
|
||||
cmd.put("limit", limit);
|
||||
}
|
||||
|
||||
if (!extraOptions.keySet().isEmpty()) {
|
||||
cmd.putAll(extraOptions);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2011 the original author or authors.
|
||||
* Copyright 2010-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,13 +17,10 @@ package org.springframework.data.mongodb.core.mapreduce;
|
||||
|
||||
public class MapReduceTiming {
|
||||
|
||||
private long mapTime;
|
||||
|
||||
private long emitLoopTime;
|
||||
|
||||
private long totalTime;
|
||||
private long mapTime, emitLoopTime, totalTime;
|
||||
|
||||
public MapReduceTiming(long mapTime, long emitLoopTime, long totalTime) {
|
||||
|
||||
this.mapTime = mapTime;
|
||||
this.emitLoopTime = emitLoopTime;
|
||||
this.totalTime = totalTime;
|
||||
@@ -41,37 +38,52 @@ public class MapReduceTiming {
|
||||
return totalTime;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MapReduceTiming [mapTime=" + mapTime + ", emitLoopTime=" + emitLoopTime + ", totalTime=" + totalTime + "]";
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
|
||||
result = prime * result + (int) (emitLoopTime ^ (emitLoopTime >>> 32));
|
||||
result = prime * result + (int) (mapTime ^ (mapTime >>> 32));
|
||||
result = prime * result + (int) (totalTime ^ (totalTime >>> 32));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
MapReduceTiming other = (MapReduceTiming) obj;
|
||||
if (emitLoopTime != other.emitLoopTime)
|
||||
return false;
|
||||
if (mapTime != other.mapTime)
|
||||
return false;
|
||||
if (totalTime != other.totalTime)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(obj instanceof MapReduceTiming)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MapReduceTiming that = (MapReduceTiming) obj;
|
||||
|
||||
return this.emitLoopTime == that.emitLoopTime && //
|
||||
this.mapTime == that.mapTime && //
|
||||
this.totalTime == that.totalTime;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.bson.BSON;
|
||||
@@ -118,7 +119,7 @@ public class Criteria implements CriteriaDefinition {
|
||||
}
|
||||
|
||||
private boolean lastOperatorWasNot() {
|
||||
return this.criteria.size() > 0 && "$not".equals(this.criteria.keySet().toArray()[this.criteria.size() - 1]);
|
||||
return !this.criteria.isEmpty() && "$not".equals(this.criteria.keySet().toArray()[this.criteria.size() - 1]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -581,9 +582,10 @@ public class Criteria implements CriteriaDefinition {
|
||||
DBObject dbo = new BasicDBObject();
|
||||
boolean not = false;
|
||||
|
||||
for (String k : this.criteria.keySet()) {
|
||||
for (Entry<String, Object> entry : criteria.entrySet()) {
|
||||
|
||||
Object value = this.criteria.get(k);
|
||||
String key = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
|
||||
if (requiresGeoJsonFormat(value)) {
|
||||
value = new BasicDBObject("$geometry", value);
|
||||
@@ -591,14 +593,14 @@ public class Criteria implements CriteriaDefinition {
|
||||
|
||||
if (not) {
|
||||
DBObject notDbo = new BasicDBObject();
|
||||
notDbo.put(k, value);
|
||||
notDbo.put(key, value);
|
||||
dbo.put("$not", notDbo);
|
||||
not = false;
|
||||
} else {
|
||||
if ("$not".equals(k) && value == null) {
|
||||
if ("$not".equals(key) && value == null) {
|
||||
not = true;
|
||||
} else {
|
||||
dbo.put(k, value);
|
||||
dbo.put(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2013 the original author or authors.
|
||||
* Copyright 2010-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -83,14 +83,10 @@ public class Field {
|
||||
|
||||
public DBObject getFieldsObject() {
|
||||
|
||||
DBObject dbo = new BasicDBObject();
|
||||
DBObject dbo = new BasicDBObject(criteria);
|
||||
|
||||
for (String k : criteria.keySet()) {
|
||||
dbo.put(k, criteria.get(k));
|
||||
}
|
||||
|
||||
for (String k : slices.keySet()) {
|
||||
dbo.put(k, new BasicDBObject("$slice", slices.get(k)));
|
||||
for (Entry<String, Object> entry : slices.entrySet()) {
|
||||
dbo.put(entry.getKey(), new BasicDBObject("$slice", entry.getValue()));
|
||||
}
|
||||
|
||||
for (Entry<String, Criteria> entry : elemMatchs.entrySet()) {
|
||||
@@ -134,8 +130,8 @@ public class Field {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean samePositionKey = this.postionKey == null ? that.postionKey == null : this.postionKey
|
||||
.equals(that.postionKey);
|
||||
boolean samePositionKey = this.postionKey == null ? that.postionKey == null
|
||||
: this.postionKey.equals(that.postionKey);
|
||||
boolean samePositionValue = this.positionValue == that.positionValue;
|
||||
|
||||
return samePositionKey && samePositionValue;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 the original author or authors.
|
||||
* Copyright 2010-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -94,9 +94,9 @@ public class Query {
|
||||
if (existing == null) {
|
||||
this.criteria.put(key, criteriaDefinition);
|
||||
} else {
|
||||
throw new InvalidMongoDbApiUsageException("Due to limitations of the com.mongodb.BasicDBObject, "
|
||||
+ "you can't add a second '" + key + "' criteria. " + "Query already contains '"
|
||||
+ existing.getCriteriaObject() + "'.");
|
||||
throw new InvalidMongoDbApiUsageException(
|
||||
"Due to limitations of the com.mongodb.BasicDBObject, " + "you can't add a second '" + key + "' criteria. "
|
||||
+ "Query already contains '" + existing.getCriteriaObject() + "'.");
|
||||
}
|
||||
|
||||
return this;
|
||||
@@ -221,10 +221,8 @@ public class Query {
|
||||
|
||||
DBObject dbo = new BasicDBObject();
|
||||
|
||||
for (String k : criteria.keySet()) {
|
||||
CriteriaDefinition c = criteria.get(k);
|
||||
DBObject cl = c.getCriteriaObject();
|
||||
dbo.putAll(cl);
|
||||
for (CriteriaDefinition definition : criteria.values()) {
|
||||
dbo.putAll(definition.getCriteriaObject());
|
||||
}
|
||||
|
||||
if (!restrictedTypes.isEmpty()) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 the original author or authors.
|
||||
* Copyright 2010-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -254,7 +254,7 @@ public class Update {
|
||||
* @return
|
||||
*/
|
||||
public Update pullAll(String key, Object[] values) {
|
||||
addFieldOperation("$pullAll", key, Arrays.copyOf(values, values.length));
|
||||
addMultiFieldOperation("$pullAll", key, Arrays.copyOf(values, values.length));
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -327,17 +327,22 @@ public class Update {
|
||||
}
|
||||
|
||||
public DBObject getUpdateObject() {
|
||||
|
||||
DBObject dbo = new BasicDBObject();
|
||||
for (String k : modifierOps.keySet()) {
|
||||
dbo.put(k, modifierOps.get(k));
|
||||
}
|
||||
return dbo;
|
||||
return new BasicDBObject(modifierOps);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is not called anymore rather override {@link #addMultiFieldOperation(String, String, Object)}.
|
||||
*
|
||||
* @param operator
|
||||
* @param key
|
||||
* @param value
|
||||
* @deprectaed Use {@link #addMultiFieldOperation(String, String, Object)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
protected void addFieldOperation(String operator, String key, Object value) {
|
||||
|
||||
Assert.hasText(key, "Key/Path for update must not be null or blank.");
|
||||
|
||||
modifierOps.put(operator, new BasicDBObject(key, value));
|
||||
this.keysToUpdate.add(key);
|
||||
}
|
||||
@@ -355,8 +360,8 @@ public class Update {
|
||||
if (existingValue instanceof BasicDBObject) {
|
||||
keyValueMap = (BasicDBObject) existingValue;
|
||||
} else {
|
||||
throw new InvalidDataAccessApiUsageException("Modifier Operations should be a LinkedHashMap but was "
|
||||
+ existingValue.getClass());
|
||||
throw new InvalidDataAccessApiUsageException(
|
||||
"Modifier Operations should be a LinkedHashMap but was " + existingValue.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -29,6 +29,7 @@ import com.mongodb.MongoException;
|
||||
* Base class to encapsulate common configuration settings when connecting to a database
|
||||
*
|
||||
* @author Mark Pollack
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public abstract class AbstractMonitor {
|
||||
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.repository.query;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.domain.Range;
|
||||
import org.springframework.data.geo.Distance;
|
||||
import org.springframework.data.geo.Point;
|
||||
@@ -34,7 +37,7 @@ import org.springframework.util.ClassUtils;
|
||||
public class MongoParametersParameterAccessor extends ParametersParameterAccessor implements MongoParameterAccessor {
|
||||
|
||||
private final MongoQueryMethod method;
|
||||
private final Object[] values;
|
||||
private final List<Object> values;
|
||||
|
||||
/**
|
||||
* Creates a new {@link MongoParametersParameterAccessor}.
|
||||
@@ -43,9 +46,11 @@ public class MongoParametersParameterAccessor extends ParametersParameterAccesso
|
||||
* @param values must not be {@literal null}.
|
||||
*/
|
||||
public MongoParametersParameterAccessor(MongoQueryMethod method, Object[] values) {
|
||||
|
||||
super(method.getParameters(), values);
|
||||
|
||||
this.method = method;
|
||||
this.values = values;
|
||||
this.values = Arrays.asList(values);
|
||||
}
|
||||
|
||||
public Range<Distance> getDistanceRange() {
|
||||
@@ -131,6 +136,6 @@ public class MongoParametersParameterAccessor extends ParametersParameterAccesso
|
||||
*/
|
||||
@Override
|
||||
public Object[] getValues() {
|
||||
return values;
|
||||
return values.toArray();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -382,7 +382,7 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
|
||||
|
||||
if (next instanceof Collection) {
|
||||
return ((Collection<?>) next).toArray();
|
||||
} else if (next.getClass().isArray()) {
|
||||
} else if (next != null && next.getClass().isArray()) {
|
||||
return (Object[]) next;
|
||||
}
|
||||
|
||||
@@ -420,7 +420,7 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
|
||||
return PUNCTATION_PATTERN.matcher(source).find() ? Pattern.quote(source) : source;
|
||||
}
|
||||
|
||||
if (source.equals("*")) {
|
||||
if ("*".equals(source)) {
|
||||
return ".*";
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,9 @@ import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.xml.bind.DatatypeConverter;
|
||||
|
||||
import org.bson.BSON;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.mongodb.core.MongoOperations;
|
||||
@@ -224,6 +227,15 @@ public class StringBasedMongoQuery extends AbstractMongoQuery {
|
||||
return (String) value;
|
||||
}
|
||||
|
||||
if (value instanceof byte[]) {
|
||||
|
||||
String base64representation = DatatypeConverter.printBase64Binary((byte[]) value);
|
||||
if (!binding.isQuoted()) {
|
||||
return "{ '$binary' : '" + base64representation + "', '$type' : " + BSON.B_GENERAL + "}";
|
||||
}
|
||||
return base64representation;
|
||||
}
|
||||
|
||||
return JSON.serialize(value);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011 by the original author(s).
|
||||
* Copyright 2011-2015 by the original author(s).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,6 +17,7 @@ package org.springframework.data.mongodb.repository.support;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.bson.types.ObjectId;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
import org.springframework.data.mongodb.repository.query.MongoEntityInformation;
|
||||
import org.springframework.data.repository.core.support.PersistentEntityInformation;
|
||||
@@ -27,12 +28,14 @@ import org.springframework.data.repository.core.support.PersistentEntityInformat
|
||||
* {@link MongoPersistentEntity} if given.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class MappingMongoEntityInformation<T, ID extends Serializable> extends PersistentEntityInformation<T, ID>
|
||||
implements MongoEntityInformation<T, ID> {
|
||||
|
||||
private final MongoPersistentEntity<T> entityMetadata;
|
||||
private final String customCollectionName;
|
||||
private final Class<ID> fallbackIdType;
|
||||
|
||||
/**
|
||||
* Creates a new {@link MappingMongoEntityInformation} for the given {@link MongoPersistentEntity}.
|
||||
@@ -40,7 +43,18 @@ public class MappingMongoEntityInformation<T, ID extends Serializable> extends P
|
||||
* @param entity must not be {@literal null}.
|
||||
*/
|
||||
public MappingMongoEntityInformation(MongoPersistentEntity<T> entity) {
|
||||
this(entity, null);
|
||||
this(entity, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link MappingMongoEntityInformation} for the given {@link MongoPersistentEntity} and fallback
|
||||
* identifier type.
|
||||
*
|
||||
* @param entity must not be {@literal null}.
|
||||
* @param fallbackIdType can be {@literal null}.
|
||||
*/
|
||||
public MappingMongoEntityInformation(MongoPersistentEntity<T> entity, Class<ID> fallbackIdType) {
|
||||
this(entity, (String) null, fallbackIdType);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -51,11 +65,26 @@ public class MappingMongoEntityInformation<T, ID extends Serializable> extends P
|
||||
* @param customCollectionName can be {@literal null}.
|
||||
*/
|
||||
public MappingMongoEntityInformation(MongoPersistentEntity<T> entity, String customCollectionName) {
|
||||
this(entity, customCollectionName, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link MappingMongoEntityInformation} for the given {@link MongoPersistentEntity}, collection name
|
||||
* and identifier type.
|
||||
*
|
||||
* @param entity must not be {@literal null}.
|
||||
* @param customCollectionName can be {@literal null}.
|
||||
* @param idType can be {@literal null}.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private MappingMongoEntityInformation(MongoPersistentEntity<T> entity, String customCollectionName,
|
||||
Class<ID> idType) {
|
||||
|
||||
super(entity);
|
||||
|
||||
this.entityMetadata = entity;
|
||||
this.customCollectionName = customCollectionName;
|
||||
this.fallbackIdType = idType != null ? idType : (Class<ID>) ObjectId.class;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
@@ -71,4 +100,19 @@ public class MappingMongoEntityInformation<T, ID extends Serializable> extends P
|
||||
public String getIdAttribute() {
|
||||
return entityMetadata.getIdProperty().getName();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.core.support.PersistentEntityInformation#getIdType()
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Class<ID> getIdType() {
|
||||
|
||||
if (this.entityMetadata.hasIdProperty()) {
|
||||
return super.getIdType();
|
||||
}
|
||||
|
||||
return fallbackIdType != null ? fallbackIdType : (Class<ID>) ObjectId.class;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ import org.springframework.util.Assert;
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Darimont
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class MongoRepositoryFactory extends RepositoryFactorySupport {
|
||||
|
||||
@@ -88,7 +89,8 @@ public class MongoRepositoryFactory extends RepositoryFactorySupport {
|
||||
@Override
|
||||
protected Object getTargetRepository(RepositoryInformation information) {
|
||||
|
||||
MongoEntityInformation<?, Serializable> entityInformation = getEntityInformation(information.getDomainType());
|
||||
MongoEntityInformation<?, Serializable> entityInformation = getEntityInformation(information.getDomainType(),
|
||||
information);
|
||||
return getTargetRepositoryViaReflection(information, entityInformation, mongoOperations);
|
||||
}
|
||||
|
||||
@@ -105,9 +107,13 @@ public class MongoRepositoryFactory extends RepositoryFactorySupport {
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.core.support.RepositoryFactorySupport#getEntityInformation(java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T, ID extends Serializable> MongoEntityInformation<T, ID> getEntityInformation(Class<T> domainClass) {
|
||||
return getEntityInformation(domainClass, null);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T, ID extends Serializable> MongoEntityInformation<T, ID> getEntityInformation(Class<T> domainClass,
|
||||
RepositoryInformation information) {
|
||||
|
||||
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(domainClass);
|
||||
|
||||
@@ -116,7 +122,8 @@ public class MongoRepositoryFactory extends RepositoryFactorySupport {
|
||||
String.format("Could not lookup mapping metadata for domain class %s!", domainClass.getName()));
|
||||
}
|
||||
|
||||
return new MappingMongoEntityInformation<T, ID>((MongoPersistentEntity<T>) entity);
|
||||
return new MappingMongoEntityInformation<T, ID>((MongoPersistentEntity<T>) entity,
|
||||
information != null ? (Class<ID>) information.getIdType() : null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -47,7 +47,7 @@ public class AuditingIntegrationTests {
|
||||
mappingContext.getPersistentEntity(Entity.class);
|
||||
|
||||
Entity entity = new Entity();
|
||||
BeforeConvertEvent<Entity> event = new BeforeConvertEvent<Entity>(entity);
|
||||
BeforeConvertEvent<Entity> event = new BeforeConvertEvent<Entity>(entity, "collection-1");
|
||||
context.publishEvent(event);
|
||||
|
||||
assertThat(entity.created, is(notNullValue()));
|
||||
@@ -55,7 +55,7 @@ public class AuditingIntegrationTests {
|
||||
|
||||
Thread.sleep(10);
|
||||
entity.id = 1L;
|
||||
event = new BeforeConvertEvent<Entity>(entity);
|
||||
event = new BeforeConvertEvent<Entity>(entity, "collection-1");
|
||||
context.publishEvent(event);
|
||||
|
||||
assertThat(entity.created, is(notNullValue()));
|
||||
|
||||
@@ -50,6 +50,7 @@ import com.mongodb.WriteConcern;
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
* @author Viktor Khoroshko
|
||||
*/
|
||||
public class MongoDbFactoryParserIntegrationTests {
|
||||
|
||||
@@ -198,6 +199,52 @@ public class MongoDbFactoryParserIntegrationTests {
|
||||
reader.loadBeanDefinitions(new ClassPathResource("namespace/mongo-client-uri-and-details.xml"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1293
|
||||
*/
|
||||
@Test
|
||||
public void setsUpClientUriWithId() {
|
||||
|
||||
reader.loadBeanDefinitions(new ClassPathResource("namespace/mongo-client-uri-and-id.xml"));
|
||||
BeanDefinition definition = factory.getBeanDefinition("testMongo");
|
||||
ConstructorArgumentValues constructorArguments = definition.getConstructorArgumentValues();
|
||||
|
||||
assertThat(constructorArguments.getArgumentCount(), is(1));
|
||||
ValueHolder argument = constructorArguments.getArgumentValue(0, MongoClientURI.class);
|
||||
assertThat(argument, is(notNullValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1293
|
||||
*/
|
||||
@Test
|
||||
public void setsUpUriWithId() {
|
||||
|
||||
reader.loadBeanDefinitions(new ClassPathResource("namespace/mongo-uri-and-id.xml"));
|
||||
BeanDefinition definition = factory.getBeanDefinition("testMongo");
|
||||
ConstructorArgumentValues constructorArguments = definition.getConstructorArgumentValues();
|
||||
|
||||
assertThat(constructorArguments.getArgumentCount(), is(1));
|
||||
ValueHolder argument = constructorArguments.getArgumentValue(0, MongoClientURI.class);
|
||||
assertThat(argument, is(notNullValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1293
|
||||
*/
|
||||
@Test(expected = BeanDefinitionParsingException.class)
|
||||
public void rejectsClientUriPlusDetailedConfigurationAndWriteConcern() {
|
||||
reader.loadBeanDefinitions(new ClassPathResource("namespace/mongo-client-uri-write-concern-and-details.xml"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1293
|
||||
*/
|
||||
@Test(expected = BeanDefinitionParsingException.class)
|
||||
public void rejectsUriPlusDetailedConfigurationAndWriteConcern() {
|
||||
reader.loadBeanDefinitions(new ClassPathResource("namespace/mongo-client-uri-write-concern-and-details.xml"));
|
||||
}
|
||||
|
||||
private static void assertWriteConcern(ClassPathXmlApplicationContext ctx, WriteConcern expectedWriteConcern) {
|
||||
|
||||
SimpleMongoDbFactory dbFactory = ctx.getBean("first", SimpleMongoDbFactory.class);
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate.CloseableIterableCursorAdapter;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate.DbObjectCallback;
|
||||
import org.springframework.data.util.CloseableIterator;
|
||||
|
||||
import com.mongodb.Cursor;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link CloseableIterableCursorAdapter}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @see DATAMONGO-1276
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class CloseableIterableCursorAdapterUnitTests {
|
||||
|
||||
@Mock PersistenceExceptionTranslator exceptionTranslator;
|
||||
@Mock DbObjectCallback<Object> callback;
|
||||
|
||||
Cursor cursor;
|
||||
CloseableIterator<Object> adapter;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
this.cursor = doThrow(IllegalArgumentException.class).when(mock(Cursor.class));
|
||||
this.adapter = new CloseableIterableCursorAdapter<Object>(cursor, exceptionTranslator, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1276
|
||||
*/
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void propagatesOriginalExceptionFromAdapterDotNext() {
|
||||
|
||||
cursor.next();
|
||||
adapter.next();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1276
|
||||
*/
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void propagatesOriginalExceptionFromAdapterDotHasNext() {
|
||||
|
||||
cursor.hasNext();
|
||||
adapter.hasNext();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1276
|
||||
*/
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void propagatesOriginalExceptionFromAdapterDotClose() {
|
||||
|
||||
cursor.close();
|
||||
adapter.close();
|
||||
}
|
||||
}
|
||||
@@ -36,7 +36,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
@ContextConfiguration("classpath:infrastructure.xml")
|
||||
public class MongoAdminIntegrationTests {
|
||||
|
||||
private static Log logger = LogFactory.getLog(MongoAdminIntegrationTests.class);
|
||||
private static final Log logger = LogFactory.getLog(MongoAdminIntegrationTests.class);
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private DB testAdminDb;
|
||||
|
||||
@@ -3035,7 +3035,7 @@ public class MongoTemplateTests {
|
||||
*/
|
||||
@Test
|
||||
public void takesLimitIntoAccountWhenStreaming() {
|
||||
|
||||
|
||||
Person youngestPerson = new Person("John", 20);
|
||||
Person oldestPerson = new Person("Jane", 42);
|
||||
|
||||
@@ -3049,6 +3049,100 @@ public class MongoTemplateTests {
|
||||
assertThat(stream.hasNext(), is(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1204
|
||||
*/
|
||||
@Test
|
||||
public void resolvesCyclicDBRefCorrectly() {
|
||||
|
||||
SomeMessage message = new SomeMessage();
|
||||
SomeContent content = new SomeContent();
|
||||
|
||||
template.save(message);
|
||||
template.save(content);
|
||||
|
||||
message.dbrefContent = content;
|
||||
content.dbrefMessage = message;
|
||||
|
||||
template.save(message);
|
||||
template.save(content);
|
||||
|
||||
SomeMessage messageLoaded = template.findOne(query(where("id").is(message.id)), SomeMessage.class);
|
||||
SomeContent contentLoaded = template.findOne(query(where("id").is(content.id)), SomeContent.class);
|
||||
|
||||
assertThat(messageLoaded.dbrefContent.id, is(contentLoaded.id));
|
||||
assertThat(contentLoaded.dbrefMessage.id, is(messageLoaded.id));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1287
|
||||
*/
|
||||
@Test
|
||||
public void shouldReuseAlreadyResolvedLazyLoadedDBRefWhenUsedAsPersistenceConstrcutorArgument() {
|
||||
|
||||
Document docInCtor = new Document();
|
||||
docInCtor.id = "doc-in-ctor";
|
||||
template.save(docInCtor);
|
||||
|
||||
DocumentWithLazyDBrefUsedInPresistenceConstructor source = new DocumentWithLazyDBrefUsedInPresistenceConstructor(
|
||||
docInCtor);
|
||||
|
||||
template.save(source);
|
||||
|
||||
DocumentWithLazyDBrefUsedInPresistenceConstructor loaded = template.findOne(query(where("id").is(source.id)),
|
||||
DocumentWithLazyDBrefUsedInPresistenceConstructor.class);
|
||||
assertThat(loaded.refToDocUsedInCtor, not(instanceOf(LazyLoadingProxy.class)));
|
||||
assertThat(loaded.refToDocNotUsedInCtor, nullValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1287
|
||||
*/
|
||||
@Test
|
||||
public void shouldNotReuseLazyLoadedDBRefWhenTypeUsedInPersistenceConstrcutorButValueRefersToAnotherProperty() {
|
||||
|
||||
Document docNotUsedInCtor = new Document();
|
||||
docNotUsedInCtor.id = "doc-but-not-used-in-ctor";
|
||||
template.save(docNotUsedInCtor);
|
||||
|
||||
DocumentWithLazyDBrefUsedInPresistenceConstructor source = new DocumentWithLazyDBrefUsedInPresistenceConstructor(
|
||||
null);
|
||||
source.refToDocNotUsedInCtor = docNotUsedInCtor;
|
||||
|
||||
template.save(source);
|
||||
|
||||
DocumentWithLazyDBrefUsedInPresistenceConstructor loaded = template.findOne(query(where("id").is(source.id)),
|
||||
DocumentWithLazyDBrefUsedInPresistenceConstructor.class);
|
||||
assertThat(loaded.refToDocNotUsedInCtor, instanceOf(LazyLoadingProxy.class));
|
||||
assertThat(loaded.refToDocUsedInCtor, nullValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1287
|
||||
*/
|
||||
@Test
|
||||
public void shouldRespectParamterValueWhenAttemptingToReuseLazyLoadedDBRefUsedInPersistenceConstrcutor() {
|
||||
|
||||
Document docInCtor = new Document();
|
||||
docInCtor.id = "doc-in-ctor";
|
||||
template.save(docInCtor);
|
||||
|
||||
Document docNotUsedInCtor = new Document();
|
||||
docNotUsedInCtor.id = "doc-but-not-used-in-ctor";
|
||||
template.save(docNotUsedInCtor);
|
||||
|
||||
DocumentWithLazyDBrefUsedInPresistenceConstructor source = new DocumentWithLazyDBrefUsedInPresistenceConstructor(
|
||||
docInCtor);
|
||||
source.refToDocNotUsedInCtor = docNotUsedInCtor;
|
||||
|
||||
template.save(source);
|
||||
|
||||
DocumentWithLazyDBrefUsedInPresistenceConstructor loaded = template.findOne(query(where("id").is(source.id)),
|
||||
DocumentWithLazyDBrefUsedInPresistenceConstructor.class);
|
||||
assertThat(loaded.refToDocUsedInCtor, not(instanceOf(LazyLoadingProxy.class)));
|
||||
assertThat(loaded.refToDocNotUsedInCtor, instanceOf(LazyLoadingProxy.class));
|
||||
}
|
||||
|
||||
static class DoucmentWithNamedIdField {
|
||||
|
||||
@Id String someIdKey;
|
||||
@@ -3351,6 +3445,7 @@ public class MongoTemplateTests {
|
||||
String id;
|
||||
String text;
|
||||
String name;
|
||||
@org.springframework.data.mongodb.core.mapping.DBRef SomeMessage dbrefMessage;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
@@ -3375,4 +3470,18 @@ public class MongoTemplateTests {
|
||||
@org.springframework.data.mongodb.core.mapping.DBRef SomeContent dbrefContent;
|
||||
SomeContent normalContent;
|
||||
}
|
||||
|
||||
static class DocumentWithLazyDBrefUsedInPresistenceConstructor {
|
||||
|
||||
@Id String id;
|
||||
@org.springframework.data.mongodb.core.mapping.DBRef(lazy = true) Document refToDocUsedInCtor;
|
||||
@org.springframework.data.mongodb.core.mapping.DBRef(lazy = true) Document refToDocNotUsedInCtor;
|
||||
|
||||
@PersistenceConstructor
|
||||
public DocumentWithLazyDBrefUsedInPresistenceConstructor(Document refToDocUsedInCtor) {
|
||||
this.refToDocUsedInCtor = refToDocUsedInCtor;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 the original author or authors.
|
||||
* Copyright 2010-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -52,6 +52,7 @@ import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
|
||||
import org.springframework.data.mongodb.core.convert.QueryMapper;
|
||||
import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexCreator;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||
import org.springframework.data.mongodb.core.mapreduce.MapReduceOptions;
|
||||
import org.springframework.data.mongodb.core.query.BasicQuery;
|
||||
import org.springframework.data.mongodb.core.query.Criteria;
|
||||
import org.springframework.data.mongodb.core.query.NearQuery;
|
||||
@@ -66,6 +67,8 @@ import com.mongodb.DB;
|
||||
import com.mongodb.DBCollection;
|
||||
import com.mongodb.DBCursor;
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.MapReduceCommand;
|
||||
import com.mongodb.MapReduceOutput;
|
||||
import com.mongodb.Mongo;
|
||||
import com.mongodb.MongoException;
|
||||
import com.mongodb.ReadPreference;
|
||||
@@ -422,6 +425,112 @@ public class MongoTemplateUnitTests extends MongoOperationsUnitTests {
|
||||
verify(this.db, times(1)).command(Mockito.any(DBObject.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1334
|
||||
*/
|
||||
@Test
|
||||
public void mapReduceShouldUseZeroAsDefaultLimit() {
|
||||
|
||||
ArgumentCaptor<MapReduceCommand> captor = ArgumentCaptor.forClass(MapReduceCommand.class);
|
||||
|
||||
MapReduceOutput output = mock(MapReduceOutput.class);
|
||||
when(output.results()).thenReturn(Collections.<DBObject> emptySet());
|
||||
when(collection.mapReduce(Mockito.any(MapReduceCommand.class))).thenReturn(output);
|
||||
|
||||
Query query = new BasicQuery("{'foo':'bar'}");
|
||||
|
||||
template.mapReduce(query, "collection", "function(){}", "function(key,values){}", Wrapper.class);
|
||||
|
||||
verify(collection).mapReduce(captor.capture());
|
||||
|
||||
assertThat(captor.getValue().getLimit(), is(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1334
|
||||
*/
|
||||
@Test
|
||||
public void mapReduceShouldPickUpLimitFromQuery() {
|
||||
|
||||
ArgumentCaptor<MapReduceCommand> captor = ArgumentCaptor.forClass(MapReduceCommand.class);
|
||||
|
||||
MapReduceOutput output = mock(MapReduceOutput.class);
|
||||
when(output.results()).thenReturn(Collections.<DBObject> emptySet());
|
||||
when(collection.mapReduce(Mockito.any(MapReduceCommand.class))).thenReturn(output);
|
||||
|
||||
Query query = new BasicQuery("{'foo':'bar'}");
|
||||
query.limit(100);
|
||||
|
||||
template.mapReduce(query, "collection", "function(){}", "function(key,values){}", Wrapper.class);
|
||||
|
||||
verify(collection).mapReduce(captor.capture());
|
||||
|
||||
assertThat(captor.getValue().getLimit(), is(100));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1334
|
||||
*/
|
||||
@Test
|
||||
public void mapReduceShouldPickUpLimitFromOptions() {
|
||||
|
||||
ArgumentCaptor<MapReduceCommand> captor = ArgumentCaptor.forClass(MapReduceCommand.class);
|
||||
|
||||
MapReduceOutput output = mock(MapReduceOutput.class);
|
||||
when(output.results()).thenReturn(Collections.<DBObject> emptySet());
|
||||
when(collection.mapReduce(Mockito.any(MapReduceCommand.class))).thenReturn(output);
|
||||
|
||||
Query query = new BasicQuery("{'foo':'bar'}");
|
||||
|
||||
template.mapReduce(query, "collection", "function(){}", "function(key,values){}",
|
||||
new MapReduceOptions().limit(1000), Wrapper.class);
|
||||
|
||||
verify(collection).mapReduce(captor.capture());
|
||||
assertThat(captor.getValue().getLimit(), is(1000));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1334
|
||||
*/
|
||||
@Test
|
||||
public void mapReduceShouldPickUpLimitFromOptionsWhenQueryIsNotPresent() {
|
||||
|
||||
ArgumentCaptor<MapReduceCommand> captor = ArgumentCaptor.forClass(MapReduceCommand.class);
|
||||
|
||||
MapReduceOutput output = mock(MapReduceOutput.class);
|
||||
when(output.results()).thenReturn(Collections.<DBObject> emptySet());
|
||||
when(collection.mapReduce(Mockito.any(MapReduceCommand.class))).thenReturn(output);
|
||||
|
||||
template.mapReduce("collection", "function(){}", "function(key,values){}", new MapReduceOptions().limit(1000),
|
||||
Wrapper.class);
|
||||
|
||||
verify(collection).mapReduce(captor.capture());
|
||||
assertThat(captor.getValue().getLimit(), is(1000));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1334
|
||||
*/
|
||||
@Test
|
||||
public void mapReduceShouldPickUpLimitFromOptionsEvenWhenQueryDefinesItDifferently() {
|
||||
|
||||
ArgumentCaptor<MapReduceCommand> captor = ArgumentCaptor.forClass(MapReduceCommand.class);
|
||||
|
||||
MapReduceOutput output = mock(MapReduceOutput.class);
|
||||
when(output.results()).thenReturn(Collections.<DBObject> emptySet());
|
||||
when(collection.mapReduce(Mockito.any(MapReduceCommand.class))).thenReturn(output);
|
||||
|
||||
Query query = new BasicQuery("{'foo':'bar'}");
|
||||
query.limit(100);
|
||||
|
||||
template.mapReduce(query, "collection", "function(){}", "function(key,values){}",
|
||||
new MapReduceOptions().limit(1000), Wrapper.class);
|
||||
|
||||
verify(collection).mapReduce(captor.capture());
|
||||
|
||||
assertThat(captor.getValue().getLimit(), is(1000));
|
||||
}
|
||||
|
||||
class AutogenerateableId {
|
||||
|
||||
@Id BigInteger id;
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core;
|
||||
|
||||
import static org.hamcrest.core.Is.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.data.mongodb.core.query.Criteria.*;
|
||||
import static org.springframework.data.mongodb.core.query.Query.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.mongodb.config.AbstractMongoConfiguration;
|
||||
import org.springframework.data.mongodb.repository.MongoRepository;
|
||||
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import com.mongodb.Mongo;
|
||||
import com.mongodb.MongoClient;
|
||||
|
||||
/**
|
||||
* Integration tests for DATAMONGO-1289.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
public class NoExplicitIdTests {
|
||||
|
||||
@Configuration
|
||||
@EnableMongoRepositories(considerNestedRepositories = true)
|
||||
static class Config extends AbstractMongoConfiguration {
|
||||
|
||||
@Override
|
||||
protected String getDatabaseName() {
|
||||
return "test";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mongo mongo() throws Exception {
|
||||
return new MongoClient();
|
||||
}
|
||||
}
|
||||
|
||||
@Autowired MongoOperations mongoOps;
|
||||
@Autowired TypeWithoutExplicitIdPropertyRepository repo;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mongoOps.dropCollection(TypeWithoutIdProperty.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1289
|
||||
*/
|
||||
@Test
|
||||
public void saveAndRetrieveTypeWithoutIdPorpertyViaTemplate() {
|
||||
|
||||
TypeWithoutIdProperty noid = new TypeWithoutIdProperty();
|
||||
noid.someString = "o.O";
|
||||
|
||||
mongoOps.save(noid);
|
||||
|
||||
TypeWithoutIdProperty retrieved = mongoOps.findOne(query(where("someString").is(noid.someString)),
|
||||
TypeWithoutIdProperty.class);
|
||||
|
||||
assertThat(retrieved.someString, is(noid.someString));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1289
|
||||
*/
|
||||
@Test
|
||||
public void saveAndRetrieveTypeWithoutIdPorpertyViaRepository() {
|
||||
|
||||
TypeWithoutIdProperty noid = new TypeWithoutIdProperty();
|
||||
noid.someString = "o.O";
|
||||
|
||||
repo.save(noid);
|
||||
|
||||
TypeWithoutIdProperty retrieved = repo.findBySomeString(noid.someString);
|
||||
assertThat(retrieved.someString, is(noid.someString));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1289
|
||||
*/
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void saveAndRetrieveTypeWithoutIdPorpertyViaRepositoryFindOne() {
|
||||
|
||||
TypeWithoutIdProperty noid = new TypeWithoutIdProperty();
|
||||
noid.someString = "o.O";
|
||||
|
||||
repo.save(noid);
|
||||
|
||||
Map<String, Object> map = mongoOps.findOne(query(where("someString").is(noid.someString)), Map.class,
|
||||
"typeWithoutIdProperty");
|
||||
|
||||
TypeWithoutIdProperty retrieved = repo.findOne(map.get("_id").toString());
|
||||
assertThat(retrieved.someString, is(noid.someString));
|
||||
}
|
||||
|
||||
static class TypeWithoutIdProperty {
|
||||
|
||||
String someString;
|
||||
}
|
||||
|
||||
static interface TypeWithoutExplicitIdPropertyRepository extends MongoRepository<TypeWithoutIdProperty, String> {
|
||||
|
||||
TypeWithoutIdProperty findBySomeString(String someString);
|
||||
}
|
||||
}
|
||||
@@ -50,7 +50,7 @@ public class UnwrapAndReadDbObjectCallbackUnitTests {
|
||||
MappingMongoConverter converter = new MappingMongoConverter(new DefaultDbRefResolver(factory),
|
||||
new MongoMappingContext());
|
||||
|
||||
this.callback = template.new UnwrapAndReadDbObjectCallback<Target>(converter, Target.class);
|
||||
this.callback = template.new UnwrapAndReadDbObjectCallback<Target>(converter, Target.class, "collection-1");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.core.convert.support.GenericConversionService;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.ObjectIdToStringConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.StringToObjectIdConverter;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.DBRef;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link AbstractMongoConverter}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class AbstractMongoConverterUnitTests {
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1324
|
||||
*/
|
||||
@Test
|
||||
public void registersObjectIdConvertersExplicitly() {
|
||||
|
||||
DefaultConversionService conversionService = spy(new DefaultConversionService());
|
||||
|
||||
new SampleMongoConverter(conversionService).afterPropertiesSet();
|
||||
|
||||
verify(conversionService).addConverter(StringToObjectIdConverter.INSTANCE);
|
||||
verify(conversionService).addConverter(ObjectIdToStringConverter.INSTANCE);
|
||||
}
|
||||
|
||||
static class SampleMongoConverter extends AbstractMongoConverter {
|
||||
|
||||
public SampleMongoConverter(GenericConversionService conversionService) {
|
||||
super(conversionService);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MongoTypeMapper getTypeMapper() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> getMappingContext() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> R read(Class<R> type, DBObject source) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Object source, DBObject sink) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convertToMongoType(Object obj, TypeInformation<?> typeInformation) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DBRef toDBRef(Object object, MongoPersistentProperty referingProperty) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2014 the original author or authors.
|
||||
* Copyright 2011-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,7 +21,9 @@ import static org.junit.Assert.*;
|
||||
import java.net.URL;
|
||||
import java.text.DateFormat;
|
||||
import java.text.Format;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.UUID;
|
||||
@@ -32,8 +34,10 @@ import org.joda.time.DateTime;
|
||||
import org.junit.Test;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.converter.ConverterFactory;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.core.convert.support.GenericConversionService;
|
||||
import org.springframework.data.convert.WritingConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.StringToBigIntegerConverter;
|
||||
import org.threeten.bp.LocalDateTime;
|
||||
|
||||
@@ -43,12 +47,11 @@ import com.mongodb.DBRef;
|
||||
* Unit tests for {@link CustomConversions}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @auhtor Christoph Strobl
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class CustomConversionsUnitTests {
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void findsBasicReadAndWriteConversions() {
|
||||
|
||||
CustomConversions conversions = new CustomConversions(Arrays.asList(FormatToStringConverter.INSTANCE,
|
||||
@@ -62,7 +65,6 @@ public class CustomConversionsUnitTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void considersSubtypesCorrectly() {
|
||||
|
||||
CustomConversions conversions = new CustomConversions(Arrays.asList(NumberToStringConverter.INSTANCE,
|
||||
@@ -132,6 +134,7 @@ public class CustomConversionsUnitTests {
|
||||
*/
|
||||
@Test
|
||||
public void doesNotConsiderTypeSimpleIfOnlyReadConverterIsRegistered() {
|
||||
|
||||
CustomConversions conversions = new CustomConversions(Arrays.asList(StringToFormatConverter.INSTANCE));
|
||||
assertThat(conversions.isSimpleType(Format.class), is(false));
|
||||
}
|
||||
@@ -257,6 +260,17 @@ public class CustomConversionsUnitTests {
|
||||
assertThat(customConversions.hasCustomWriteTarget(LocalDateTime.class), is(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1302
|
||||
*/
|
||||
@Test
|
||||
public void registersConverterFactoryCorrectly() {
|
||||
|
||||
CustomConversions customConversions = new CustomConversions(Collections.singletonList(new FormatConverterFactory()));
|
||||
|
||||
assertThat(customConversions.getCustomWriteTarget(String.class, SimpleDateFormat.class), notNullValue());
|
||||
}
|
||||
|
||||
private static Class<?> createProxyTypeFor(Class<?> type) {
|
||||
|
||||
ProxyFactory factory = new ProxyFactory();
|
||||
@@ -331,4 +345,37 @@ public class CustomConversionsUnitTests {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@WritingConverter
|
||||
static class FormatConverterFactory implements ConverterFactory<String, Format> {
|
||||
|
||||
@Override
|
||||
public <T extends Format> Converter<String, T> getConverter(Class<T> targetType) {
|
||||
return new StringToFormat<T>(targetType);
|
||||
}
|
||||
|
||||
private static final class StringToFormat<T extends Format> implements Converter<String, T> {
|
||||
|
||||
private final Class<T> targetType;
|
||||
|
||||
public StringToFormat(Class<T> targetType) {
|
||||
this.targetType = targetType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T convert(String source) {
|
||||
|
||||
if (source.length() == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return targetType.newInstance();
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,6 +79,28 @@ public class DBObjectAccessorUnitTests {
|
||||
new DBObjectAccessor(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1335
|
||||
*/
|
||||
@Test
|
||||
public void writesAllNestingsCorrectly() {
|
||||
|
||||
MongoPersistentEntity<?> entity = context.getPersistentEntity(TypeWithTwoNestings.class);
|
||||
|
||||
BasicDBObject target = new BasicDBObject();
|
||||
|
||||
DBObjectAccessor accessor = new DBObjectAccessor(target);
|
||||
accessor.put(entity.getPersistentProperty("id"), "id");
|
||||
accessor.put(entity.getPersistentProperty("b"), "b");
|
||||
accessor.put(entity.getPersistentProperty("c"), "c");
|
||||
|
||||
DBObject nestedA = DBObjectTestUtils.getAsDBObject(target, "a");
|
||||
|
||||
assertThat(nestedA, is(notNullValue()));
|
||||
assertThat(nestedA.get("b"), is((Object) "b"));
|
||||
assertThat(nestedA.get("c"), is((Object) "c"));
|
||||
}
|
||||
|
||||
static class ProjectingType {
|
||||
|
||||
String name;
|
||||
@@ -91,4 +113,10 @@ public class DBObjectAccessorUnitTests {
|
||||
String c;
|
||||
}
|
||||
|
||||
static class TypeWithTwoNestings {
|
||||
|
||||
String id;
|
||||
@Field("a.b") String b;
|
||||
@Field("a.c") String c;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2402,10 +2402,10 @@ public class MappingMongoConverterUnitTests {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (source.equals("foo-enum-value")) {
|
||||
if ("foo-enum-value".equals(source)) {
|
||||
return FooBarEnum.FOO;
|
||||
}
|
||||
if (source.equals("bar-enum-value")) {
|
||||
if ("bar-enum-value".equals(source)) {
|
||||
return FooBarEnum.BAR;
|
||||
}
|
||||
|
||||
|
||||
@@ -790,6 +790,34 @@ public class QueryMapperUnitTests {
|
||||
assertThat(dbo, isBsonObject().containing("geoJsonPoint.$geoIntersects.$geometry.coordinates"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1269
|
||||
*/
|
||||
@Test
|
||||
public void mappingShouldRetainNumericMapKey() {
|
||||
|
||||
Query query = query(where("map.1.stringProperty").is("ba'alzamon"));
|
||||
|
||||
DBObject dbo = mapper.getMappedObject(query.getQueryObject(),
|
||||
context.getPersistentEntity(EntityWithComplexValueTypeMap.class));
|
||||
|
||||
assertThat(dbo.containsField("map.1.stringProperty"), is(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1269
|
||||
*/
|
||||
@Test
|
||||
public void mappingShouldRetainNumericPositionInList() {
|
||||
|
||||
Query query = query(where("list.1.stringProperty").is("ba'alzamon"));
|
||||
|
||||
DBObject dbo = mapper.getMappedObject(query.getQueryObject(),
|
||||
context.getPersistentEntity(EntityWithComplexValueTypeList.class));
|
||||
|
||||
assertThat(dbo.containsField("list.1.stringProperty"), is(true));
|
||||
}
|
||||
|
||||
@Document
|
||||
public class Foo {
|
||||
@Id private ObjectId id;
|
||||
@@ -890,4 +918,18 @@ public class QueryMapperUnitTests {
|
||||
GeoJsonPoint geoJsonPoint;
|
||||
@Field("geoJsonPointWithNameViaFieldAnnotation") GeoJsonPoint namedGeoJsonPoint;
|
||||
}
|
||||
|
||||
static class SimpeEntityWithoutId {
|
||||
|
||||
String stringProperty;
|
||||
Integer integerProperty;
|
||||
}
|
||||
|
||||
static class EntityWithComplexValueTypeMap {
|
||||
Map<Integer, SimpeEntityWithoutId> map;
|
||||
}
|
||||
|
||||
static class EntityWithComplexValueTypeList {
|
||||
List<SimpeEntityWithoutId> list;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Suite;
|
||||
import org.junit.runners.Suite.SuiteClasses;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.geo.Point;
|
||||
import org.springframework.data.mongodb.core.DBObjectTestUtils;
|
||||
import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexResolver.IndexDefinitionHolder;
|
||||
@@ -148,6 +149,34 @@ public class MongoPersistentEntityIndexResolverUnitTests {
|
||||
assertThat(indexDefinitions.get(0).getCollection(), equalTo("CollectionOverride"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1297
|
||||
*/
|
||||
@Test
|
||||
public void resolvesIndexOnDbrefWhenDefined() {
|
||||
|
||||
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(WithDbRef.class);
|
||||
|
||||
assertThat(indexDefinitions, hasSize(1));
|
||||
assertThat(indexDefinitions.get(0).getCollection(), equalTo("withDbRef"));
|
||||
assertThat(indexDefinitions.get(0).getIndexKeys(), equalTo(new BasicDBObjectBuilder().add("indexedDbRef", 1)
|
||||
.get()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1297
|
||||
*/
|
||||
@Test
|
||||
public void resolvesIndexOnDbrefWhenDefinedOnNestedElement() {
|
||||
|
||||
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(WrapperOfWithDbRef.class);
|
||||
|
||||
assertThat(indexDefinitions, hasSize(1));
|
||||
assertThat(indexDefinitions.get(0).getCollection(), equalTo("wrapperOfWithDbRef"));
|
||||
assertThat(indexDefinitions.get(0).getIndexKeys(),
|
||||
equalTo(new BasicDBObjectBuilder().add("nested.indexedDbRef", 1).get()));
|
||||
}
|
||||
|
||||
@Document(collection = "Zero")
|
||||
static class IndexOnLevelZero {
|
||||
@Indexed String indexedProperty;
|
||||
@@ -182,6 +211,24 @@ public class MongoPersistentEntityIndexResolverUnitTests {
|
||||
@Indexed @Field("customFieldName") String namedProperty;
|
||||
}
|
||||
|
||||
@Document
|
||||
static class WrapperOfWithDbRef {
|
||||
WithDbRef nested;
|
||||
}
|
||||
|
||||
@Document
|
||||
static class WithDbRef {
|
||||
|
||||
@Indexed//
|
||||
@DBRef//
|
||||
NoIndex indexedDbRef;
|
||||
}
|
||||
|
||||
@Document(collection = "no-index")
|
||||
static class NoIndex {
|
||||
@Id String id;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -39,7 +39,7 @@ public class AbstractMongoEventListenerUnitTests {
|
||||
@Test
|
||||
public void invokesCallbackForEventForPerson() {
|
||||
|
||||
MongoMappingEvent<Person> event = new BeforeConvertEvent<Person>(new Person("Dave", "Matthews"));
|
||||
MongoMappingEvent<Person> event = new BeforeConvertEvent<Person>(new Person("Dave", "Matthews"), "collection-1");
|
||||
SamplePersonEventListener listener = new SamplePersonEventListener();
|
||||
listener.onApplicationEvent(event);
|
||||
assertThat(listener.invokedOnBeforeConvert, is(true));
|
||||
@@ -54,11 +54,11 @@ public class AbstractMongoEventListenerUnitTests {
|
||||
SamplePersonEventListener listener = new SamplePersonEventListener();
|
||||
context.addApplicationListener(listener);
|
||||
|
||||
context.publishEvent(new BeforeConvertEvent<Person>(new Person("Dave", "Matthews")));
|
||||
context.publishEvent(new BeforeConvertEvent<Person>(new Person("Dave", "Matthews"), "collection-1"));
|
||||
assertThat(listener.invokedOnBeforeConvert, is(true));
|
||||
|
||||
listener.invokedOnBeforeConvert = false;
|
||||
context.publishEvent(new BeforeConvertEvent<String>("Test"));
|
||||
context.publishEvent(new BeforeConvertEvent<String>("Test", "collection-1"));
|
||||
assertThat(listener.invokedOnBeforeConvert, is(false));
|
||||
|
||||
context.close();
|
||||
@@ -71,7 +71,7 @@ public class AbstractMongoEventListenerUnitTests {
|
||||
public void afterLoadEffectGetsHandledCorrectly() {
|
||||
|
||||
SamplePersonEventListener listener = new SamplePersonEventListener();
|
||||
listener.onApplicationEvent(new AfterLoadEvent<Person>(new BasicDBObject(), Person.class));
|
||||
listener.onApplicationEvent(new AfterLoadEvent<Person>(new BasicDBObject(), Person.class, "collection-1"));
|
||||
assertThat(listener.invokedOnAfterLoad, is(true));
|
||||
}
|
||||
|
||||
@@ -83,8 +83,8 @@ public class AbstractMongoEventListenerUnitTests {
|
||||
|
||||
SamplePersonEventListener personListener = new SamplePersonEventListener();
|
||||
SampleAccountEventListener accountListener = new SampleAccountEventListener();
|
||||
personListener.onApplicationEvent(new AfterLoadEvent<Person>(new BasicDBObject(), Person.class));
|
||||
accountListener.onApplicationEvent(new AfterLoadEvent<Person>(new BasicDBObject(), Person.class));
|
||||
personListener.onApplicationEvent(new AfterLoadEvent<Person>(new BasicDBObject(), Person.class, "collection-1"));
|
||||
accountListener.onApplicationEvent(new AfterLoadEvent<Person>(new BasicDBObject(), Person.class, "collection-1"));
|
||||
|
||||
assertThat(personListener.invokedOnAfterLoad, is(true));
|
||||
assertThat(accountListener.invokedOnAfterLoad, is(false));
|
||||
@@ -98,8 +98,8 @@ public class AbstractMongoEventListenerUnitTests {
|
||||
|
||||
SamplePersonEventListener personListener = new SamplePersonEventListener();
|
||||
SampleContactEventListener contactListener = new SampleContactEventListener();
|
||||
personListener.onApplicationEvent(new AfterLoadEvent<Person>(new BasicDBObject(), Person.class));
|
||||
contactListener.onApplicationEvent(new AfterLoadEvent<Person>(new BasicDBObject(), Person.class));
|
||||
personListener.onApplicationEvent(new AfterLoadEvent<Person>(new BasicDBObject(), Person.class, "collection-1"));
|
||||
contactListener.onApplicationEvent(new AfterLoadEvent<Person>(new BasicDBObject(), Person.class, "collection-1"));
|
||||
|
||||
assertThat(personListener.invokedOnAfterLoad, is(true));
|
||||
assertThat(contactListener.invokedOnAfterLoad, is(true));
|
||||
@@ -113,8 +113,8 @@ public class AbstractMongoEventListenerUnitTests {
|
||||
|
||||
SamplePersonEventListener personListener = new SamplePersonEventListener();
|
||||
SampleContactEventListener contactListener = new SampleContactEventListener();
|
||||
personListener.onApplicationEvent(new AfterLoadEvent<Contact>(new BasicDBObject(), Contact.class));
|
||||
contactListener.onApplicationEvent(new AfterLoadEvent<Contact>(new BasicDBObject(), Contact.class));
|
||||
personListener.onApplicationEvent(new AfterLoadEvent<Contact>(new BasicDBObject(), Contact.class, "collection-1"));
|
||||
contactListener.onApplicationEvent(new AfterLoadEvent<Contact>(new BasicDBObject(), Contact.class, "collection-1"));
|
||||
|
||||
assertThat(personListener.invokedOnAfterLoad, is(false));
|
||||
assertThat(contactListener.invokedOnAfterLoad, is(true));
|
||||
@@ -137,7 +137,7 @@ public class AbstractMongoEventListenerUnitTests {
|
||||
@Test
|
||||
public void invokeContactCallbackForPersonEvent() {
|
||||
|
||||
MongoMappingEvent<DBObject> event = new BeforeDeleteEvent<Person>(new BasicDBObject(), Person.class);
|
||||
MongoMappingEvent<DBObject> event = new BeforeDeleteEvent<Person>(new BasicDBObject(), Person.class, "collection-1");
|
||||
SampleContactEventListener listener = new SampleContactEventListener();
|
||||
listener.onApplicationEvent(event);
|
||||
|
||||
@@ -150,7 +150,7 @@ public class AbstractMongoEventListenerUnitTests {
|
||||
@Test
|
||||
public void invokePersonCallbackForPersonEvent() {
|
||||
|
||||
MongoMappingEvent<DBObject> event = new BeforeDeleteEvent<Person>(new BasicDBObject(), Person.class);
|
||||
MongoMappingEvent<DBObject> event = new BeforeDeleteEvent<Person>(new BasicDBObject(), Person.class, "collection-1");
|
||||
SamplePersonEventListener listener = new SamplePersonEventListener();
|
||||
listener.onApplicationEvent(event);
|
||||
|
||||
@@ -163,7 +163,8 @@ public class AbstractMongoEventListenerUnitTests {
|
||||
@Test
|
||||
public void dontInvokePersonCallbackForAccountEvent() {
|
||||
|
||||
MongoMappingEvent<DBObject> event = new BeforeDeleteEvent<Account>(new BasicDBObject(), Account.class);
|
||||
MongoMappingEvent<DBObject> event = new BeforeDeleteEvent<Account>(new BasicDBObject(), Account.class,
|
||||
"collection-1");
|
||||
SamplePersonEventListener listener = new SamplePersonEventListener();
|
||||
listener.onApplicationEvent(event);
|
||||
|
||||
@@ -176,7 +177,7 @@ public class AbstractMongoEventListenerUnitTests {
|
||||
@Test
|
||||
public void donInvokePersonCallbackForUntypedEvent() {
|
||||
|
||||
MongoMappingEvent<DBObject> event = new BeforeDeleteEvent<Account>(new BasicDBObject(), null);
|
||||
MongoMappingEvent<DBObject> event = new BeforeDeleteEvent<Account>(new BasicDBObject(), null, "collection-1");
|
||||
SamplePersonEventListener listener = new SamplePersonEventListener();
|
||||
listener.onApplicationEvent(event);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011 by the original author(s).
|
||||
* Copyright (c) 2011-2015 by the original author(s).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,7 +15,10 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.mapping.event;
|
||||
|
||||
import static org.hamcrest.core.Is.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.data.mongodb.core.query.Criteria.*;
|
||||
import static org.springframework.data.mongodb.core.query.Query.*;
|
||||
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
@@ -26,6 +29,7 @@ import org.junit.Test;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.data.mongodb.core.aggregation.Aggregation;
|
||||
import org.springframework.data.mongodb.core.mapping.PersonPojoStringId;
|
||||
|
||||
import com.mongodb.DB;
|
||||
@@ -38,10 +42,13 @@ import com.mongodb.WriteConcern;
|
||||
* Integration test for Mapping Events.
|
||||
*
|
||||
* @author Mark Pollack
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class ApplicationContextEventTests {
|
||||
|
||||
private final String[] collectionsToDrop = new String[] { "personPojoStringId" };
|
||||
private static final String COLLECTION_NAME = "personPojoStringId";
|
||||
|
||||
private final String[] collectionsToDrop = new String[] { COLLECTION_NAME };
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
private MongoTemplate template;
|
||||
@@ -60,6 +67,7 @@ public class ApplicationContextEventTests {
|
||||
}
|
||||
|
||||
private void cleanDb() throws UnknownHostException {
|
||||
|
||||
Mongo mongo = new MongoClient();
|
||||
DB db = mongo.getDB("database");
|
||||
for (String coll : collectionsToDrop) {
|
||||
@@ -90,6 +98,9 @@ public class ApplicationContextEventTests {
|
||||
assertEquals(1, simpleMappingEventListener.onBeforeSaveEvents.size());
|
||||
assertEquals(1, simpleMappingEventListener.onAfterSaveEvents.size());
|
||||
|
||||
assertEquals(COLLECTION_NAME, simpleMappingEventListener.onBeforeSaveEvents.get(0).getCollectionName());
|
||||
assertEquals(COLLECTION_NAME, simpleMappingEventListener.onAfterSaveEvents.get(0).getCollectionName());
|
||||
|
||||
Assert.assertTrue(personBeforeSaveListener.seenEvents.get(0) instanceof BeforeSaveEvent<?>);
|
||||
Assert.assertTrue(afterSaveListener.seenEvents.get(0) instanceof AfterSaveEvent<?>);
|
||||
|
||||
@@ -106,7 +117,75 @@ public class ApplicationContextEventTests {
|
||||
dbo = beforeSaveEvent.getDBObject();
|
||||
|
||||
comparePersonAndDbo(p, p2, dbo);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1256
|
||||
*/
|
||||
@Test
|
||||
public void loadAndConvertEvents() {
|
||||
|
||||
SimpleMappingEventListener simpleMappingEventListener = applicationContext
|
||||
.getBean(SimpleMappingEventListener.class);
|
||||
|
||||
PersonPojoStringId entity = new PersonPojoStringId("1", "Text");
|
||||
template.insert(entity);
|
||||
|
||||
template.findOne(query(where("id").is(entity.getId())), PersonPojoStringId.class);
|
||||
|
||||
assertThat(simpleMappingEventListener.onAfterLoadEvents.size(), is(1));
|
||||
assertThat(simpleMappingEventListener.onAfterLoadEvents.get(0).getCollectionName(), is(COLLECTION_NAME));
|
||||
|
||||
assertThat(simpleMappingEventListener.onBeforeConvertEvents.size(), is(1));
|
||||
assertThat(simpleMappingEventListener.onBeforeConvertEvents.get(0).getCollectionName(), is(COLLECTION_NAME));
|
||||
|
||||
assertThat(simpleMappingEventListener.onAfterConvertEvents.size(), is(1));
|
||||
assertThat(simpleMappingEventListener.onAfterConvertEvents.get(0).getCollectionName(), is(COLLECTION_NAME));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1256
|
||||
*/
|
||||
@Test
|
||||
public void loadEventsOnAggregation() {
|
||||
|
||||
SimpleMappingEventListener simpleMappingEventListener = applicationContext
|
||||
.getBean(SimpleMappingEventListener.class);
|
||||
|
||||
template.insert(new PersonPojoStringId("1", "Text"));
|
||||
|
||||
template.aggregate(Aggregation.newAggregation(Aggregation.project("text")), PersonPojoStringId.class,
|
||||
PersonPojoStringId.class);
|
||||
|
||||
assertThat(simpleMappingEventListener.onAfterLoadEvents.size(), is(1));
|
||||
assertThat(simpleMappingEventListener.onAfterLoadEvents.get(0).getCollectionName(), is(COLLECTION_NAME));
|
||||
|
||||
assertThat(simpleMappingEventListener.onBeforeConvertEvents.size(), is(1));
|
||||
assertThat(simpleMappingEventListener.onBeforeConvertEvents.get(0).getCollectionName(), is(COLLECTION_NAME));
|
||||
|
||||
assertThat(simpleMappingEventListener.onAfterConvertEvents.size(), is(1));
|
||||
assertThat(simpleMappingEventListener.onAfterConvertEvents.get(0).getCollectionName(), is(COLLECTION_NAME));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1256
|
||||
*/
|
||||
@Test
|
||||
public void deleteEvents() {
|
||||
|
||||
SimpleMappingEventListener simpleMappingEventListener = applicationContext
|
||||
.getBean(SimpleMappingEventListener.class);
|
||||
|
||||
PersonPojoStringId entity = new PersonPojoStringId("1", "Text");
|
||||
template.insert(entity);
|
||||
|
||||
template.remove(entity);
|
||||
|
||||
assertThat(simpleMappingEventListener.onBeforeDeleteEvents.size(), is(1));
|
||||
assertThat(simpleMappingEventListener.onBeforeDeleteEvents.get(0).getCollectionName(), is(COLLECTION_NAME));
|
||||
|
||||
assertThat(simpleMappingEventListener.onAfterDeleteEvents.size(), is(1));
|
||||
assertThat(simpleMappingEventListener.onAfterDeleteEvents.get(0).getCollectionName(), is(COLLECTION_NAME));
|
||||
}
|
||||
|
||||
private void comparePersonAndDbo(PersonPojoStringId p, PersonPojoStringId p2, DBObject dbo) {
|
||||
|
||||
@@ -78,7 +78,7 @@ public class AuditingEventListenerUnitTests {
|
||||
public void triggersCreationMarkForObjectWithEmptyId() {
|
||||
|
||||
Sample sample = new Sample();
|
||||
listener.onApplicationEvent(new BeforeConvertEvent<Object>(sample));
|
||||
listener.onApplicationEvent(new BeforeConvertEvent<Object>(sample, "collection-1"));
|
||||
|
||||
verify(handler, times(1)).markCreated(sample);
|
||||
verify(handler, times(0)).markModified(any(Sample.class));
|
||||
@@ -92,7 +92,7 @@ public class AuditingEventListenerUnitTests {
|
||||
|
||||
Sample sample = new Sample();
|
||||
sample.id = "id";
|
||||
listener.onApplicationEvent(new BeforeConvertEvent<Object>(sample));
|
||||
listener.onApplicationEvent(new BeforeConvertEvent<Object>(sample, "collection-1"));
|
||||
|
||||
verify(handler, times(0)).markCreated(any(Sample.class));
|
||||
verify(handler, times(1)).markModified(sample);
|
||||
|
||||
@@ -21,8 +21,6 @@ import java.util.List;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.data.mongodb.core.mapping.PersonPojoStringId;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
public class PersonBeforeSaveListener extends AbstractMongoEventListener<PersonPojoStringId> {
|
||||
|
||||
public final List<ApplicationEvent> seenEvents = new ArrayList<ApplicationEvent>();
|
||||
@@ -32,7 +30,7 @@ public class PersonBeforeSaveListener extends AbstractMongoEventListener<PersonP
|
||||
* @see org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener#onBeforeSave(java.lang.Object, com.mongodb.DBObject)
|
||||
*/
|
||||
@Override
|
||||
public void onBeforeSave(PersonPojoStringId source, DBObject dbo) {
|
||||
seenEvents.add(new BeforeSaveEvent<PersonPojoStringId>(source, dbo));
|
||||
public void onBeforeSave(BeforeSaveEvent<PersonPojoStringId> event) {
|
||||
seenEvents.add(event);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011 by the original author(s).
|
||||
* Copyright (c) 2011-2015 by the original author(s).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,8 +17,12 @@ package org.springframework.data.mongodb.core.mapping.event;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* @author Mark Pollak
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Leiter
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class SimpleMappingEventListener extends AbstractMongoEventListener<Object> {
|
||||
|
||||
public final ArrayList<BeforeConvertEvent<Object>> onBeforeConvertEvents = new ArrayList<BeforeConvertEvent<Object>>();
|
||||
@@ -26,29 +30,41 @@ public class SimpleMappingEventListener extends AbstractMongoEventListener<Objec
|
||||
public final ArrayList<AfterSaveEvent<Object>> onAfterSaveEvents = new ArrayList<AfterSaveEvent<Object>>();
|
||||
public final ArrayList<AfterLoadEvent<Object>> onAfterLoadEvents = new ArrayList<AfterLoadEvent<Object>>();
|
||||
public final ArrayList<AfterConvertEvent<Object>> onAfterConvertEvents = new ArrayList<AfterConvertEvent<Object>>();
|
||||
public final ArrayList<BeforeDeleteEvent<Object>> onBeforeDeleteEvents = new ArrayList<BeforeDeleteEvent<Object>>();
|
||||
public final ArrayList<AfterDeleteEvent<Object>> onAfterDeleteEvents = new ArrayList<AfterDeleteEvent<Object>>();
|
||||
|
||||
@Override
|
||||
public void onBeforeConvert(Object source) {
|
||||
onBeforeConvertEvents.add(new BeforeConvertEvent<Object>(source));
|
||||
public void onBeforeConvert(BeforeConvertEvent<Object> event) {
|
||||
onBeforeConvertEvents.add(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBeforeSave(Object source, DBObject dbo) {
|
||||
onBeforeSaveEvents.add(new BeforeSaveEvent<Object>(source, dbo));
|
||||
public void onBeforeSave(BeforeSaveEvent<Object> event) {
|
||||
onBeforeSaveEvents.add(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAfterSave(Object source, DBObject dbo) {
|
||||
onAfterSaveEvents.add(new AfterSaveEvent<Object>(source, dbo));
|
||||
public void onAfterSave(AfterSaveEvent<Object> event) {
|
||||
onAfterSaveEvents.add(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAfterLoad(DBObject dbo) {
|
||||
onAfterLoadEvents.add(new AfterLoadEvent<Object>(dbo, Object.class));
|
||||
public void onAfterLoad(AfterLoadEvent<Object> event) {
|
||||
onAfterLoadEvents.add(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAfterConvert(DBObject dbo, Object source) {
|
||||
onAfterConvertEvents.add(new AfterConvertEvent<Object>(dbo, source));
|
||||
public void onAfterConvert(AfterConvertEvent<Object> event) {
|
||||
onAfterConvertEvents.add(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAfterDelete(AfterDeleteEvent<Object> event) {
|
||||
onAfterDeleteEvents.add(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBeforeDelete(BeforeDeleteEvent<Object> event) {
|
||||
onBeforeDeleteEvents.add(event);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2011 the original author or authors.
|
||||
* Copyright 2010-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,12 +15,40 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.mapreduce;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.data.mongodb.test.util.IsBsonObject.*;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Mark Pollack
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class MapReduceOptionsTests {
|
||||
|
||||
@Test
|
||||
public void testFinalize() {
|
||||
new MapReduceOptions().finalizeFunction("code");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1334
|
||||
*/
|
||||
@Test
|
||||
public void limitShouldBeIncludedCorrectly() {
|
||||
|
||||
MapReduceOptions options = new MapReduceOptions();
|
||||
options.limit(10);
|
||||
|
||||
assertThat(options.getOptionsObject(), isBsonObject().containing("limit", 10));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1334
|
||||
*/
|
||||
@Test
|
||||
public void limitShouldNotBePresentInDboWhenNotSet() {
|
||||
assertThat(new MapReduceOptions().getOptionsObject(), isBsonObject().notContaining("limit"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,13 +118,13 @@ public class MapReduceTests {
|
||||
|
||||
int size = 0;
|
||||
for (ContentAndVersion cv : results) {
|
||||
if (cv.getId().equals("Resume")) {
|
||||
if ("Resume".equals(cv.getId())) {
|
||||
assertEquals(6, cv.getValue().longValue());
|
||||
}
|
||||
if (cv.getId().equals("Schema")) {
|
||||
if ("Schema".equals(cv.getId())) {
|
||||
assertEquals(2, cv.getValue().longValue());
|
||||
}
|
||||
if (cv.getId().equals("mongoDB How-To")) {
|
||||
if ("mongoDB How-To".equals(cv.getId())) {
|
||||
assertEquals(2, cv.getValue().longValue());
|
||||
}
|
||||
size++;
|
||||
@@ -141,13 +141,13 @@ public class MapReduceTests {
|
||||
new MapReduceOptions().outputCollection("jmr2_out"), NumberAndVersion.class);
|
||||
int size = 0;
|
||||
for (NumberAndVersion nv : results) {
|
||||
if (nv.getId().equals("1")) {
|
||||
if ("1".equals(nv.getId())) {
|
||||
assertEquals(2, nv.getValue().longValue());
|
||||
}
|
||||
if (nv.getId().equals("2")) {
|
||||
if ("2".equals(nv.getId())) {
|
||||
assertEquals(6, nv.getValue().longValue());
|
||||
}
|
||||
if (nv.getId().equals("3")) {
|
||||
if ("3".equals(nv.getId())) {
|
||||
assertEquals(2, nv.getValue().longValue());
|
||||
}
|
||||
size++;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 the original author or authors.
|
||||
* Copyright 2010-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -23,9 +23,11 @@ import java.util.Map;
|
||||
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.mongodb.core.DBObjectTestUtils;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.BasicDBObjectBuilder;
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* Test cases for {@link Update}.
|
||||
@@ -484,4 +486,22 @@ public class UpdateTests {
|
||||
public void pushShouldThrowExceptionWhenGivenNegativePosition() {
|
||||
new Update().push("foo").atPosition(-1).each("booh");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1346
|
||||
*/
|
||||
@Test
|
||||
public void registersMultiplePullAllClauses() {
|
||||
|
||||
Update update = new Update();
|
||||
update.pullAll("field1", new String[] { "foo" });
|
||||
update.pullAll("field2", new String[] { "bar" });
|
||||
|
||||
DBObject updateObject = update.getUpdateObject();
|
||||
|
||||
DBObject pullAll = DBObjectTestUtils.getAsDBObject(updateObject, "$pullAll");
|
||||
|
||||
assertThat(pullAll.get("field1"), is(notNullValue()));
|
||||
assertThat(pullAll.get("field2"), is(notNullValue()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -661,6 +661,20 @@ public class MongoQueryCreatorUnitTests {
|
||||
assertThat(query, is(query(where("username").regex(".*"))));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1342
|
||||
*/
|
||||
@Test
|
||||
public void bindsNullValueToContainsClause() {
|
||||
|
||||
PartTree partTree = new PartTree("emailAddressesContains", User.class);
|
||||
|
||||
ConvertingParameterAccessor accessor = getAccessor(converter, new Object[] { null });
|
||||
Query query = new MongoQueryCreator(partTree, accessor, context).createQuery();
|
||||
|
||||
assertThat(query, is(query(where("emailAddresses").in((Object) null))));
|
||||
}
|
||||
|
||||
interface PersonRepository extends Repository<Person, Long> {
|
||||
|
||||
List<Person> findByLocationNearAndFirstname(Point location, Distance maxDistance, String firstname);
|
||||
|
||||
@@ -24,6 +24,9 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.bind.DatatypeConverter;
|
||||
|
||||
import org.bson.BSON;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -343,6 +346,23 @@ public class StringBasedMongoQueryUnitTests {
|
||||
assertThat(query.getQueryObject(), is(reference.getQueryObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1290
|
||||
*/
|
||||
@Test
|
||||
public void shouldSupportNonQuotedBinaryDataReplacement() throws Exception {
|
||||
|
||||
byte[] binaryData = "Matthews".getBytes("UTF-8");
|
||||
ConvertingParameterAccessor accesor = StubParameterAccessor.getAccessor(converter, binaryData);
|
||||
StringBasedMongoQuery mongoQuery = createQueryForMethod("findByLastnameAsBinary", byte[].class);
|
||||
|
||||
org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accesor);
|
||||
org.springframework.data.mongodb.core.query.Query reference = new BasicQuery("{'lastname' : { '$binary' : '"
|
||||
+ DatatypeConverter.printBase64Binary(binaryData) + "', '$type' : " + BSON.B_GENERAL + "}}");
|
||||
|
||||
assertThat(query.getQueryObject(), is(reference.getQueryObject()));
|
||||
}
|
||||
|
||||
private StringBasedMongoQuery createQueryForMethod(String name, Class<?>... parameters) throws Exception {
|
||||
|
||||
Method method = SampleRepository.class.getMethod(name, parameters);
|
||||
@@ -355,6 +375,9 @@ public class StringBasedMongoQueryUnitTests {
|
||||
@Query("{ 'lastname' : ?0 }")
|
||||
Person findByLastname(String lastname);
|
||||
|
||||
@Query("{ 'lastname' : ?0 }")
|
||||
Person findByLastnameAsBinary(byte[] lastname);
|
||||
|
||||
@Query("{ 'lastname' : '?0' }")
|
||||
Person findByLastnameQuoted(String lastname);
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<mongo:db-factory id="testMongo" client-uri="mongodb://username:password@localhost/database" />
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<mongo:db-factory client-uri="mongodb://username:password@localhost/database" write-concern="NORMAL" username="username" />
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<mongo:db-factory id="testMongo" uri="mongodb://username:password@localhost/database" />
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<mongo:db-factory uri="mongodb://username:password@localhost/database" write-concern="NORMAL" username="username" />
|
||||
|
||||
</beans>
|
||||
@@ -16,6 +16,7 @@ Import-Template:
|
||||
javax.tools.*;version="0",
|
||||
javax.net.*;version="0",
|
||||
javax.validation.*;version="${validation:[=.=.=.=,+1.0.0)}";resolution:=optional,
|
||||
javax.xml.bind.*;version=0,
|
||||
org.aopalliance.*;version="[1.0.0, 2.0.0)";resolution:=optional,
|
||||
org.bson.*;version="0",
|
||||
org.objenesis.*;version="${objenesis:[=.=.=, +1.0.0)}";resolution:=optional,
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
[[new-features]]
|
||||
= New & Noteworthy
|
||||
|
||||
[[new-features.1-8-0]]
|
||||
== What's new in Spring Data MongoDB 1.8
|
||||
|
||||
* `Criteria` offers support for creating `$geoIntersects`.
|
||||
* Support http://docs.spring.io/spring/docs/current/spring-framework-reference/html/expressions.html[SpEL expressions] in `@Query`.
|
||||
* `MongoMappingEvents` expose the collection name they are issued for.
|
||||
* Improved support for `<mongo:mongo-client credentials="..." />`.
|
||||
* Improved index creation failure error message.
|
||||
|
||||
[[new-features.1-7-0]]
|
||||
== What's new in Spring Data MongoDB 1.7
|
||||
|
||||
|
||||
@@ -211,6 +211,7 @@ The MappingMongoConverter can use metadata to drive the mapping of objects to do
|
||||
* `@PersistenceConstructor` - marks a given constructor - even a package protected one - to use when instantiating the object from the database. Constructor arguments are mapped by name to the key values in the retrieved DBObject.
|
||||
* `@Value` - this annotation is part of the Spring Framework . Within the mapping framework it can be applied to constructor arguments. This lets you use a Spring Expression Language statement to transform a key's value retrieved in the database before it is used to construct a domain object. In order to reference a property of a given document one has to use expressions like: `@Value("#root.myProperty")` where `root` refers to the root of the given document.
|
||||
* `@Field` - applied at the field level and described the name of the field as it will be represented in the MongoDB BSON document thus allowing the name to be different than the fieldname of the class.
|
||||
* `@Version` - applied at field level is used for optimistic locking and checked for modification on save operations. The initial value is `zero` which is bumped automatically on every update.
|
||||
|
||||
The mapping metadata infrastructure is defined in a seperate spring-data-commons project that is technology agnostic. Specific subclasses are using in the MongoDB support to support annotation based metadata. Other strategies are also possible to put in place if there is demand.
|
||||
|
||||
|
||||
@@ -381,7 +381,7 @@ MongoDB repository support integrates with the http://www.querydsl.com/[QueryDSL
|
||||
* Adopts better to refactoring changes in domain types
|
||||
* Incremental query definition is easier
|
||||
|
||||
Please refer to the QueryDSL documentation which describes how to bootstrap your environment for APT based code generation http://source.mysema.com/static/querydsl/2.1.2/reference/html/ch02.html#d0e112[using Maven] or http://source.mysema.com/static/querydsl/2.1.2/reference/html/ch02.html#d0e131[using Ant].
|
||||
Please refer to the http://www.querydsl.com/static/querydsl/latest/reference/html/[QueryDSL documentation] which describes how to bootstrap your environment for APT based code generation using Maven or Ant.
|
||||
|
||||
Using QueryDSL you will be able to write queries as shown below
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ You will also need to add the location of the Spring Milestone repository for ma
|
||||
</repositories>
|
||||
----
|
||||
|
||||
The repository is also http://shrub.appspot.com/maven.springframework.org/milestone/org/springframework/data/[browseable here].
|
||||
The repository is also http://repo.spring.io/milestone/org/springframework/data/[browseable here].
|
||||
|
||||
You may also want to set the logging level to `DEBUG` to see some additional information, edit the log4j.properties file to have
|
||||
|
||||
@@ -938,6 +938,40 @@ You can use several overloaded methods to remove an object from the database.
|
||||
|
||||
* *remove* Remove the given document based on one of the following: a specific object instance, a query document criteria combined with a class or a query document criteria combined with a specific collection name.
|
||||
|
||||
[[mongo-template.optimistic-locking]]
|
||||
=== Optimistic locking
|
||||
|
||||
The `@Version` annotation provides a JPA similar semantic in the context of MongoDB and makes sure updates are only applied to documents with matching version. Therefore the actual value of the version property is added to the update query in a way that the update won't have any effect if another operation altered the document in between. In that case an `OptimisticLockingFailureException` is thrown.
|
||||
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
@Document
|
||||
class Person {
|
||||
|
||||
@Id String id;
|
||||
String firstname;
|
||||
String lastname;
|
||||
@Version Long version;
|
||||
}
|
||||
|
||||
Person daenerys = template.insert(new Person("Daenerys")); <1>
|
||||
|
||||
Person tmp = teplate.findOne(query(where("id").is(daenerys.getId())), Person.class); <2>
|
||||
|
||||
daenerys.setLastname("Targaryen");
|
||||
template.save(daenerys); <3>
|
||||
|
||||
template.save(tmp); // throws OptimisticLockingFailureException <4>
|
||||
----
|
||||
<1> Intially insert document. `version` is set to `0`.
|
||||
<2> Load the just inserted document `version` is still `0`.
|
||||
<3> Update document with `version = 0`. Set the `lastname` and bump `version` to `1`.
|
||||
<4> Try to update previously loaded document sill having `version = 0` fails with `OptimisticLockingFailureException` as the current `version` is `1`.
|
||||
====
|
||||
|
||||
IMPORTANT: Using MongoDB driver version 3 requires to set the `WriteConcern` to `ACKNOWLEDGED`. Otherwise `OptimisticLockingFailureException` can be silently swallowed.
|
||||
|
||||
[[mongo.query]]
|
||||
== Querying Documents
|
||||
|
||||
@@ -1159,13 +1193,13 @@ The geo near operations return a `GeoResults` wrapper object that encapsulates `
|
||||
[[mongo.geo-json]]
|
||||
=== GeoJSON Support
|
||||
|
||||
MongoDB supports http://geojeson.org/[GeoJSON] and simple (legacy) coordinate pairs for geospatial data. Those formats can both be used for storing as well as querying data.
|
||||
MongoDB supports http://geojson.org/[GeoJSON] and simple (legacy) coordinate pairs for geospatial data. Those formats can both be used for storing as well as querying data.
|
||||
|
||||
NOTE: Please refer to the http://docs.mongodb.org/manual/core/2dsphere/#geospatial-indexes-store-geojson/[MongoDB manual on GeoJSON support] to learn about requirements and restrictions.
|
||||
|
||||
==== GeoJSON types in domain classes
|
||||
|
||||
Usage of http://geojeson.org/[GeoJSON] types in domain classes is straight forward. The `org.springframework.data.mongodb.core.geo` package contains types like `GeoJsonPoint`, `GeoJsonPolygon` and others. Those are extensions to the existing `org.springframework.data.geo` types.
|
||||
Usage of http://geojson.org/[GeoJSON] types in domain classes is straight forward. The `org.springframework.data.mongodb.core.geo` package contains types like `GeoJsonPoint`, `GeoJsonPolygon` and others. Those are extensions to the existing `org.springframework.data.geo` types.
|
||||
|
||||
====
|
||||
[source,java]
|
||||
|
||||
@@ -1,6 +1,46 @@
|
||||
Spring Data MongoDB Changelog
|
||||
=============================
|
||||
|
||||
Changes in version 1.8.2.RELEASE (2015-12-18)
|
||||
---------------------------------------------
|
||||
* DATAMONGO-1355 - Release 1.8.2 (Gosling).
|
||||
* DATAMONGO-1346 - Cannot add two pullAll to an Update.
|
||||
* DATAMONGO-1342 - Potential NullPointerException in MongoQueryCreator.nextAsArray(…).
|
||||
* DATAMONGO-1337 - General code quality improvements.
|
||||
* DATAMONGO-1335 - DBObjectAccessor doesn't write properties correctly if multiple ones are nested.
|
||||
* DATAMONGO-1334 - MapResultOptions limit not implemented.
|
||||
* DATAMONGO-1324 - StringToObjectIdConverter not properly registered causing drop in performance on identifier conversion.
|
||||
* DATAMONGO-1317 - Assert compatibility with MongoDB Java driver 3.2.
|
||||
* DATAMONGO-1290 - @Query annotation with byte[] parameter does not work.
|
||||
* DATAMONGO-1289 - NullPointerException when saving an object with no "id" field or @Id annotation.
|
||||
* DATAMONGO-1287 - MappingMongoConverter eagerly fetches and converts lazy DbRef to change them afterwards by proxies.
|
||||
* DATAMONGO-1204 - ObjectPath equality check breaks due to changes MongoDB V3.
|
||||
|
||||
|
||||
Changes in version 1.8.1.RELEASE (2015-11-15)
|
||||
---------------------------------------------
|
||||
* DATAMONGO-1316 - Release 1.8.1 (Gosling).
|
||||
* DATAMONGO-1312 - Cannot convert generic sub-document fields.
|
||||
* DATAMONGO-1302 - CustomConversions should allow registration of ConverterFactory.
|
||||
* DATAMONGO-1297 - Unique Index on DBRef.
|
||||
* DATAMONGO-1293 - MongoDbFactoryParser should allow id attribute in addition to client-uri.
|
||||
* DATAMONGO-1276 - MongoTemplate.CloseableIterableCursorAdapter does not null check return values from PersistenceExceptionTranslator.
|
||||
|
||||
|
||||
Changes in version 1.6.4.RELEASE (2015-10-14)
|
||||
---------------------------------------------
|
||||
* DATAMONGO-1304 - Release 1.6.4 (Evans).
|
||||
|
||||
|
||||
Changes in version 1.8.0.RELEASE (2015-09-01)
|
||||
---------------------------------------------
|
||||
* DATAMONGO-1282 - Release 1.8 GA (Gosling).
|
||||
* DATAMONGO-1280 - Add what's new section to refrence documentation.
|
||||
* DATAMONGO-1275 - Reference documentation should mention support for optimistic locking.
|
||||
* DATAMONGO-1269 - QueryMapper drops numeric keys in Maps.
|
||||
* DATAMONGO-1256 - Provide a collectionName in MongoMappingEvents.
|
||||
|
||||
|
||||
Changes in version 1.8.0.RC1 (2015-08-04)
|
||||
-----------------------------------------
|
||||
* DATAMONGO-1268 - Release 1.8 RC1 (Gosling).
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Spring Data MongoDB 1.8 RC1
|
||||
Spring Data MongoDB 1.8.2
|
||||
Copyright (c) [2010-2015] Pivotal Software, Inc.
|
||||
|
||||
This product is licensed to you under the Apache License, Version 2.0 (the "License").
|
||||
|
||||
Reference in New Issue
Block a user