diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml
index 655571c91..3d2b56fdd 100644
--- a/spring-data-mongodb/pom.xml
+++ b/spring-data-mongodb/pom.xml
@@ -35,7 +35,7 @@
org.springframework.data
spring-data-commons-core
- 1.0.0.M3
+ 1.0.0.BUILD-SNAPSHOT
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/AbstractMongoQuery.java
similarity index 78%
rename from spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoQuery.java
rename to spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/AbstractMongoQuery.java
index 310a6ff0e..c6b72d0c1 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoQuery.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/AbstractMongoQuery.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2010 the original author or authors.
+ * Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,10 +24,10 @@ import org.springframework.data.document.mongodb.MongoTemplate;
import org.springframework.data.document.mongodb.query.Query;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
+import org.springframework.data.repository.query.ParameterAccessor;
+import org.springframework.data.repository.query.ParametersParameterAccessor;
import org.springframework.data.repository.query.QueryMethod;
import org.springframework.data.repository.query.RepositoryQuery;
-import org.springframework.data.repository.query.SimpleParameterAccessor;
-import org.springframework.data.repository.query.parser.PartTree;
import org.springframework.util.Assert;
import com.mongodb.DBCollection;
@@ -36,32 +36,30 @@ import com.mongodb.DBObject;
/**
- * {@link RepositoryQuery} implementation for Mongo.
+ * Base class for {@link RepositoryQuery} implementations for Mongo.
*
* @author Oliver Gierke
*/
-public class MongoQuery implements RepositoryQuery {
+public abstract class AbstractMongoQuery implements RepositoryQuery {
private final QueryMethod method;
private final MongoTemplate template;
- private final PartTree tree;
/**
- * Creates a new {@link MongoQuery} from the given {@link QueryMethod} and
+ * Creates a new {@link AbstractMongoQuery} from the given {@link QueryMethod} and
* {@link MongoTemplate}.
*
* @param method
* @param template
*/
- public MongoQuery(QueryMethod method, MongoTemplate template) {
+ public AbstractMongoQuery(QueryMethod method, MongoTemplate template) {
Assert.notNull(template);
Assert.notNull(method);
this.method = method;
this.template = template;
- this.tree = new PartTree(method.getName(), method.getDomainClass());
}
@@ -74,22 +72,27 @@ public class MongoQuery implements RepositoryQuery {
*/
public Object execute(Object[] parameters) {
- SimpleParameterAccessor accessor =
- new SimpleParameterAccessor(method.getParameters(), parameters);
-
- MongoQueryCreator creator =
- new MongoQueryCreator(tree, accessor, template.getConverter());
- Query query = creator.createQuery();
+ ParameterAccessor accessor =
+ new ParametersParameterAccessor(method.getParameters(), parameters);
+ Query query = createQuery(new ConvertingParameterAccessor(template.getConverter(), accessor));
if (method.isCollectionQuery()) {
return new CollectionExecution().execute(query);
} else if (method.isPageQuery()) {
- return new PagedExecution(creator, accessor.getPageable())
- .execute(query);
+ return new PagedExecution(accessor.getPageable()).execute(query);
} else {
return new SingleEntityExecution().execute(query);
}
}
+
+ /**
+ * Create a {@link Query} instance using the given {@link ParameterAccessor}
+ * @param accessor
+ * @param converter
+ * @return
+ */
+ protected abstract Query createQuery(ConvertingParameterAccessor accessor);
+
private abstract class Execution {
@@ -133,7 +136,6 @@ public class MongoQuery implements RepositoryQuery {
class PagedExecution extends Execution {
private final Pageable pageable;
- private final MongoQueryCreator creator;
/**
@@ -141,11 +143,9 @@ public class MongoQuery implements RepositoryQuery {
*
* @param pageable
*/
- public PagedExecution(MongoQueryCreator creator, Pageable pageable) {
+ public PagedExecution(Pageable pageable) {
- Assert.notNull(creator);
Assert.notNull(pageable);
- this.creator = creator;
this.pageable = pageable;
}
@@ -161,10 +161,8 @@ public class MongoQuery implements RepositoryQuery {
@SuppressWarnings({ "rawtypes", "unchecked" })
Object execute(Query query) {
- Query countQuery = creator.createQuery();
String collectionName = getCollectionName(method.getDomainClass());
- int count =
- getCollectionCursor(collectionName, countQuery.getQueryObject()).count();
+ int count = getCollectionCursor(collectionName, query.getQueryObject()).count();
List> result =
template.find(collectionName, applyPagination(query, pageable),
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/ConvertingParameterAccessor.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/ConvertingParameterAccessor.java
new file mode 100644
index 000000000..b884d38d1
--- /dev/null
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/ConvertingParameterAccessor.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.data.document.mongodb.repository;
+
+import java.util.Iterator;
+
+import org.springframework.data.document.mongodb.MongoWriter;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.repository.query.ParameterAccessor;
+
+import com.mongodb.BasicDBObject;
+import com.mongodb.DBObject;
+
+/**
+ * Custom {@link ParameterAccessor} that uses a {@link MongoWriter} to serialize parameters into Mongo format.
+ *
+ * @author Oliver Gierke
+ */
+public class ConvertingParameterAccessor implements ParameterAccessor {
+
+ private final MongoWriter writer;
+ private final ParameterAccessor delegate;
+
+ /**
+ * Creates a new {@link ConvertingParameterAccessor} with the given {@link MongoWriter} and delegate.
+ *
+ * @param writer
+ */
+ public ConvertingParameterAccessor(MongoWriter writer, ParameterAccessor delegate) {
+ this.writer = writer;
+ this.delegate = delegate;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Iterable#iterator()
+ */
+ public Iterator iterator() {
+ return new ConvertingIterator(delegate.iterator());
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.springframework.data.repository.query.ParameterAccessor#getPageable()
+ */
+ public Pageable getPageable() {
+ return delegate.getPageable();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.springframework.data.repository.query.ParameterAccessor#getSort()
+ */
+ public Sort getSort() {
+ return delegate.getSort();
+ }
+
+ /**
+ * Custom {@link Iterator} to convert items before returning them.
+ *
+ * @author Oliver Gierke
+ */
+ private class ConvertingIterator implements Iterator {
+
+ private final Iterator delegate;
+
+ /**
+ * Creates a new {@link ConvertingIterator} for the given delegate.
+ *
+ * @param delegate
+ */
+ public ConvertingIterator(Iterator delegate) {
+ this.delegate = delegate;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.util.Iterator#hasNext()
+ */
+ public boolean hasNext() {
+ return delegate.hasNext();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.util.Iterator#next()
+ */
+ public Object next() {
+
+ DBObject result = new BasicDBObject();
+ writer.write(new ValueHolder(delegate.next()), result);
+ return result.get("value");
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.util.Iterator#remove()
+ */
+ public void remove() {
+ delegate.remove();
+ }
+ }
+
+ /**
+ * Simple value holder class to allow conversion and accessing the converted value in a deterministic way.
+ *
+ * @author Oliver Gierke
+ */
+ private static class ValueHolder {
+
+ private Object value;
+
+ public ValueHolder(Object value) {
+
+ this.value = value;
+ }
+
+ @SuppressWarnings("unused")
+ public Object getValue() {
+
+ return value;
+ }
+ }
+}
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoQueryCreator.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoQueryCreator.java
index 5455ad393..43669c027 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoQueryCreator.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoQueryCreator.java
@@ -18,25 +18,22 @@ package org.springframework.data.document.mongodb.repository;
import static org.springframework.data.document.mongodb.query.Criteria.*;
import java.util.Collections;
+import java.util.Iterator;
import java.util.regex.Pattern;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.springframework.data.document.mongodb.MongoConverter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.data.document.mongodb.query.Criteria;
import org.springframework.data.document.mongodb.query.CriteriaDefinition;
import org.springframework.data.document.mongodb.query.Query;
import org.springframework.data.domain.Sort;
-import org.springframework.data.repository.query.SimpleParameterAccessor;
-import org.springframework.data.repository.query.SimpleParameterAccessor.BindableParameterIterator;
+import org.springframework.data.repository.query.ParameterAccessor;
+import org.springframework.data.repository.query.ParametersParameterAccessor;
import org.springframework.data.repository.query.parser.AbstractQueryCreator;
import org.springframework.data.repository.query.parser.Part;
import org.springframework.data.repository.query.parser.Part.Type;
import org.springframework.data.repository.query.parser.PartTree;
-import com.mongodb.BasicDBObject;
-import com.mongodb.DBObject;
-
/**
* Custom query creator to create Mongo criterias.
@@ -45,36 +42,28 @@ import com.mongodb.DBObject;
*/
class MongoQueryCreator extends AbstractQueryCreator {
- private static final Log LOG = LogFactory.getLog(MongoQueryCreator.class);
- private final MongoConverter converter;
+ private static final Logger LOG = LoggerFactory.getLog(MongoQueryCreator.class);
/**
* Creates a new {@link MongoQueryCreator} from the given {@link PartTree}
- * and {@link SimpleParameterAccessor}.
+ * and {@link ParametersParameterAccessor}.
*
* @param tree
* @param accessor
*/
- public MongoQueryCreator(PartTree tree,
- SimpleParameterAccessor accessor, MongoConverter converter) {
+ public MongoQueryCreator(PartTree tree, ParameterAccessor accessor) {
super(tree, accessor);
- this.converter = converter;
}
/*
* (non-Javadoc)
- *
- * @see
- * org.springframework.data.document.mongodb.repository.AbstractQueryCreator
- * #create(org.springframework.data.repository.query.parser.Part,
- * org.springframework
- * .data.repository.query.SimpleParameterAccessor.BindableParameterIterator)
+ * @see org.springframework.data.repository.query.parser.AbstractQueryCreator#create(org.springframework.data.repository.query.parser.Part, java.util.Iterator)
*/
@Override
- protected Criteria create(Part part, BindableParameterIterator iterator) {
+ protected Criteria create(Part part, Iterator iterator) {
return from(part.getType(),
where(part.getProperty().toDotPath()), iterator);
@@ -83,16 +72,11 @@ class MongoQueryCreator extends AbstractQueryCreator {
/*
* (non-Javadoc)
- *
- * @see
- * org.springframework.data.document.mongodb.repository.AbstractQueryCreator
- * #handlePart(org.springframework.data.repository.query.parser.Part,
- * org.springframework
- * .data.repository.query.SimpleParameterAccessor.BindableParameterIterator)
+ * @see org.springframework.data.repository.query.parser.AbstractQueryCreator#and(org.springframework.data.repository.query.parser.Part, java.lang.Object, java.util.Iterator)
*/
@Override
protected Criteria and(Part part, Criteria base,
- BindableParameterIterator iterator) {
+ Iterator iterator) {
return from(part.getType(), where(part.getProperty().toDotPath()),
iterator);
@@ -143,16 +127,16 @@ class MongoQueryCreator extends AbstractQueryCreator {
* @return
*/
private Criteria from(Type type, Criteria criteria,
- BindableParameterIterator parameters) {
+ Iterator parameters) {
switch (type) {
case GREATER_THAN:
- return criteria.gt(getConvertedParameter(parameters));
+ return criteria.gt(parameters.next());
case LESS_THAN:
- return criteria.lt(getConvertedParameter(parameters));
+ return criteria.lt(parameters.next());
case BETWEEN:
- return criteria.gt(getConvertedParameter(parameters)).lt(
- getConvertedParameter(parameters));
+ return criteria.gt(parameters.next()).lt(
+ parameters.next());
case IS_NOT_NULL:
return criteria.not().is(null);
case IS_NULL:
@@ -161,22 +145,15 @@ class MongoQueryCreator extends AbstractQueryCreator {
String value = parameters.next().toString();
return criteria.is(toLikeRegex(value));
case SIMPLE_PROPERTY:
- return criteria.is(getConvertedParameter(parameters));
+ return criteria.is(parameters.next());
case NEGATING_SIMPLE_PROPERTY:
- return criteria.not().is(getConvertedParameter(parameters));
+ return criteria.not().is(parameters.next());
}
throw new IllegalArgumentException("Unsupported keyword!");
}
- private Object getConvertedParameter(BindableParameterIterator parameters) {
-
- DBObject result = new BasicDBObject();
- converter.write(new ValueHolder(parameters.next()), result);
- return result.get("value");
- }
-
private Pattern toLikeRegex(String source) {
@@ -184,27 +161,5 @@ class MongoQueryCreator extends AbstractQueryCreator {
return Pattern.compile(regex);
}
- /**
- * Simple value holder class to allow conversion and accessing the converted
- * value in a deterministic way.
- *
- * @author Oliver Gierke
- */
- private static class ValueHolder {
-
- private Object value;
-
-
- public ValueHolder(Object value) {
-
- this.value = value;
- }
-
-
- @SuppressWarnings("unused")
- public Object getValue() {
-
- return value;
- }
- }
+
}
\ No newline at end of file
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoQueryMethod.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoQueryMethod.java
new file mode 100644
index 000000000..ec921de1b
--- /dev/null
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoQueryMethod.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.data.document.mongodb.repository;
+
+import java.lang.reflect.Method;
+
+import org.springframework.core.annotation.AnnotationUtils;
+import org.springframework.data.repository.query.QueryMethod;
+import org.springframework.util.StringUtils;
+
+/**
+ *
+ * TODO - Extract methods for {@link #getAnnotatedQuery()} into superclass as it is currently copied from Spring Data
+ * JPA
+ * @author Oliver Gierke
+ */
+class MongoQueryMethod extends QueryMethod {
+
+ private final Method method;
+
+ /**
+ * Creates a new {@link MongoQueryMethod} from the given {@link Method}.
+ *
+ * @param method
+ */
+ public MongoQueryMethod(Method method) {
+ super(method);
+ this.method = method;
+ }
+
+ boolean hasAnnotatedQuery() {
+ return getAnnotatedQuery() != null;
+ }
+
+ /**
+ * Returns the query string declared in a {@link Query} annotation or {@literal null} if neither the annotation
+ * found nor the attribute was specified.
+ *
+ * @return
+ */
+ String getAnnotatedQuery() {
+
+ String query = (String) AnnotationUtils.getValue(getQueryAnnotation());
+ return StringUtils.hasText(query) ? query : null;
+ }
+
+ /**
+ * Returns the {@link Query} annotation that is applied to the method or {@code null} if none available.
+ *
+ * @return
+ */
+ private Query getQueryAnnotation() {
+
+ return method.getAnnotation(Query.class);
+ }
+}
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoRepositoryFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoRepositoryFactoryBean.java
index c9b9cc7c0..5d3154645 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoRepositoryFactoryBean.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoRepositoryFactoryBean.java
@@ -23,7 +23,6 @@ import org.springframework.data.document.mongodb.MongoTemplate;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.query.QueryLookupStrategy;
import org.springframework.data.repository.query.QueryLookupStrategy.Key;
-import org.springframework.data.repository.query.QueryMethod;
import org.springframework.data.repository.query.RepositoryQuery;
import org.springframework.data.repository.support.RepositoryFactoryBeanSupport;
import org.springframework.data.repository.support.RepositoryFactorySupport;
@@ -126,15 +125,21 @@ public class MongoRepositoryFactoryBean extends
}
/**
- * {@link QueryLookupStrategy} to create {@link MongoQuery} instances.
+ * {@link QueryLookupStrategy} to create {@link PartTreeMongoQuery} instances.
*
* @author Oliver Gierke
*/
private class MongoQueryLookupStrategy implements QueryLookupStrategy {
public RepositoryQuery resolveQuery(Method method) {
-
- return new MongoQuery(new QueryMethod(method), template);
+
+ MongoQueryMethod queryMethod = new MongoQueryMethod(method);
+
+ if (queryMethod.hasAnnotatedQuery()) {
+ return new StringBasedMongoQuery(queryMethod, template);
+ } else {
+ return new PartTreeMongoQuery(queryMethod, template);
+ }
}
}
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/PartTreeMongoQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/PartTreeMongoQuery.java
new file mode 100644
index 000000000..b6221b8e9
--- /dev/null
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/PartTreeMongoQuery.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2002-2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.data.document.mongodb.repository;
+
+import org.springframework.data.document.mongodb.MongoTemplate;
+import org.springframework.data.document.mongodb.query.Query;
+import org.springframework.data.repository.query.QueryMethod;
+import org.springframework.data.repository.query.RepositoryQuery;
+import org.springframework.data.repository.query.parser.PartTree;
+
+/**
+ * {@link RepositoryQuery} implementation for Mongo.
+ *
+ * @author Oliver Gierke
+ */
+public class PartTreeMongoQuery extends AbstractMongoQuery {
+
+ private final PartTree tree;
+
+ /**
+ * Creates a new {@link PartTreeMongoQuery} from the given {@link QueryMethod} and {@link MongoTemplate}.
+ *
+ * @param method
+ * @param template
+ */
+ public PartTreeMongoQuery(QueryMethod method, MongoTemplate template) {
+
+ super(method, template);
+ this.tree = new PartTree(method.getName(), method.getDomainClass());
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.springframework.data.document.mongodb.repository.AbstractMongoQuery#createQuery(org.springframework.data.
+ * document.mongodb.repository.ConvertingParameterAccessor)
+ */
+ @Override
+ protected Query createQuery(ConvertingParameterAccessor accessor) {
+
+ MongoQueryCreator creator = new MongoQueryCreator(tree, accessor);
+ return creator.createQuery();
+ }
+}
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/Query.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/Query.java
new file mode 100644
index 000000000..86b5aa60d
--- /dev/null
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/Query.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.data.document.mongodb.repository;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+
+/**
+ * Annotation to declare finder queries directly on repository methods.
+ *
+ * @author Oliver Gierke
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+@Documented
+public @interface Query {
+
+ String value() default "";
+}
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/SimpleMongoRepository.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/SimpleMongoRepository.java
index 9c00add21..1a4611f16 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/SimpleMongoRepository.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/SimpleMongoRepository.java
@@ -122,7 +122,7 @@ public class SimpleMongoRepository extends
*/
public boolean exists(ID id) {
- return findById(id) == null;
+ return findById(id) != null;
}
@@ -157,10 +157,13 @@ public class SimpleMongoRepository extends
* org.springframework.data.repository.Repository#delete(java.lang.Object)
*/
public void delete(T entity) {
+
+ Object id = entityInformation.getId(entity);
+ ObjectId objectId = template.getConverter().convertObjectId(id);
Query query =
- new Query(where(entityInformation.getFieldName()).is(
- entityInformation.getId(entity)));
+ new Query(where("_id").is(
+ objectId));
template.remove(getCollectionName(getDomainClass()), query);
}
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/StringBasedMongoQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/StringBasedMongoQuery.java
new file mode 100644
index 000000000..6f1cfe41c
--- /dev/null
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/StringBasedMongoQuery.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.data.document.mongodb.repository;
+
+import java.util.Iterator;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.data.document.mongodb.MongoTemplate;
+import org.springframework.data.document.mongodb.query.BasicQuery;
+import org.springframework.data.document.mongodb.query.Query;
+
+/**
+ * Query to use a plain JSON String to create the {@link Query} to actually execute.
+ *
+ * @author Oliver Gierke
+ */
+public class StringBasedMongoQuery extends AbstractMongoQuery {
+
+ private static final Pattern PLACEHOLDER = Pattern.compile("\\?");
+ private static final Logger LOG = LoggerFactory.getLogger(StringBasedMongoQuery.class);
+
+ private final String query;
+
+ /**
+ * Creates a new {@link StringBasedMongoQuery}.
+ *
+ * @param method
+ * @param template
+ */
+ public StringBasedMongoQuery(MongoQueryMethod method, MongoTemplate template) {
+ super(method, template);
+ this.query = method.getAnnotatedQuery();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.springframework.data.document.mongodb.repository.AbstractMongoQuery#createQuery(org.springframework.data.
+ * repository.query.SimpleParameterAccessor, org.springframework.data.document.mongodb.MongoConverter)
+ */
+ @Override
+ protected Query createQuery(ConvertingParameterAccessor accessor) {
+
+ Matcher matcher = PLACEHOLDER.matcher(query);
+ Iterator iterator = accessor.iterator();
+ String result = null;
+
+ while (matcher.find()) {
+ String group = matcher.group();
+ result = query.replace(group, String.format("\"%s\"", iterator.next()));
+ }
+
+ Query query = new BasicQuery(result);
+ LOG.debug("Created query {}", query.getQueryObject());
+
+ return query;
+ }
+}
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java
index 50f122442..353aa34c6 100644
--- a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java
@@ -8,6 +8,7 @@ import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
+import org.bson.types.ObjectId;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -19,116 +20,146 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* Base class for tests for {@link PersonRepository}.
- *
+ *
* @author Oliver Gierke
*/
@RunWith(SpringJUnit4ClassRunner.class)
public abstract class AbstractPersonRepositoryIntegrationTests {
- @Autowired
- protected PersonRepository repository;
- Person dave, carter, boyd,stefan,leroi;
+ @Autowired
+ protected PersonRepository repository;
+ Person dave, carter, boyd, stefan, leroi;
- @Before
- public void setUp() {
-
- repository.deleteAll();
-
- dave = new Person("Dave", "Matthews", 42);
- carter = new Person("Carter", "Beauford", 49);
- boyd = new Person("Boyd", "Tinsley", 45);
- stefan = new Person("Stefan", "Lessard", 34);
- leroi = new Person("Leroi", "Moore", 41);
-
- repository.save(Arrays.asList(dave, carter, boyd, stefan, leroi));
- }
-
- @Test
+ @Before
+ public void setUp() {
+
+ repository.deleteAll();
+
+ dave = new Person("Dave", "Matthews", 42);
+ carter = new Person("Carter", "Beauford", 49);
+ boyd = new Person("Boyd", "Tinsley", 45);
+ stefan = new Person("Stefan", "Lessard", 34);
+ leroi = new Person("Leroi", "Moore", 41);
+
+ repository.save(Arrays.asList(dave, carter, boyd, stefan, leroi));
+ }
+
+ @Test
+ public void existsWorksCorrectly() {
+ assertThat(repository.exists(dave.getId()), is(true));
+ assertThat(repository.exists(carter.getId()), is(true));
+ assertThat(repository.exists(boyd.getId()), is(true));
+ assertThat(repository.exists(stefan.getId()), is(true));
+ assertThat(repository.exists(leroi.getId()), is(true));
+ assertThat(repository.exists(new ObjectId().toString()), is(false));
+ }
+
+ @Test
public void findsPersonById() throws Exception {
-
- assertThat(repository.findById(dave.getId()), is(dave));
+
+ assertThat(repository.findById(dave.getId()), is(dave));
}
- @Test
- public void findsPersonsByLastname() throws Exception {
-
- List result = repository.findByLastname("Beauford");
- assertThat(result.size(), is(1));
- assertThat(result, hasItem(carter));
- }
+ @Test
+ public void findsAllMusicians() throws Exception {
+ List result = repository.findAll();
+ assertThat(result, hasItems(dave, carter, boyd, stefan, leroi));
+ assertThat(result.size(), is(5));
+ }
+
+ @Test
+ public void deletesPersonCorrectly() throws Exception {
+
+ repository.delete(dave);
+
+ List result = repository.findAll();
+
+ assertThat(result.size(), is(4));
+ assertThat(result, not(hasItem(dave)));
+ }
- @Test
- public void findsPersonsByFirstnameLike() throws Exception {
-
- List result = repository.findByFirstnameLike("Bo*");
- assertThat(result.size(), is(1));
- assertThat(result, hasItem(boyd));
- }
+ @Test
+ public void findsPersonsByLastname() throws Exception {
- @Test
- public void findsPagedPersons() throws Exception {
-
- Page result =
- repository.findAll(new PageRequest(1, 2, Direction.ASC,
- "lastname"));
- assertThat(result.isFirstPage(), is(false));
- assertThat(result.isLastPage(), is(false));
- assertThat(result, hasItems(dave, leroi));
- }
+ List result = repository.findByLastname("Beauford");
+ assertThat(result.size(), is(1));
+ assertThat(result, hasItem(carter));
+ }
+
+ @Test
+ public void finsPersonsByFirstname() {
+
+ List result = repository.findByThePersonsFirstname("Leroi");
+ assertThat(result.size(), is(1));
+ assertThat(result, hasItem(leroi));
+ }
- @Test
- public void executesPagedFinderCorrectly() throws Exception {
-
- Page page =
- repository.findByLastnameLike("*a*", new PageRequest(0, 2,
- Direction.ASC, "lastname"));
- assertThat(page.isFirstPage(), is(true));
- assertThat(page.isLastPage(), is(false));
- assertThat(page.getNumberOfElements(), is(2));
- assertThat(page, hasItems(carter, stefan));
- }
+ @Test
+ public void findsPersonsByFirstnameLike() throws Exception {
-
- @Test
- public void findsPersonInAgeRangeCorrectly() throws Exception {
+ List result = repository.findByFirstnameLike("Bo*");
+ assertThat(result.size(), is(1));
+ assertThat(result, hasItem(boyd));
+ }
- List result = repository.findByAgeBetween(40, 45);
- assertThat(result.size(), is(2));
- assertThat(result, hasItems(dave, leroi));
- }
-
-
- @Test
+ @Test
+ public void findsPagedPersons() throws Exception {
+
+ Page result = repository.findAll(new PageRequest(1, 2, Direction.ASC, "lastname"));
+ assertThat(result.isFirstPage(), is(false));
+ assertThat(result.isLastPage(), is(false));
+ assertThat(result, hasItems(dave, leroi));
+ }
+
+ @Test
+ public void executesPagedFinderCorrectly() throws Exception {
+
+ Page page = repository.findByLastnameLike("*a*", new PageRequest(0, 2, Direction.ASC, "lastname"));
+ assertThat(page.isFirstPage(), is(true));
+ assertThat(page.isLastPage(), is(false));
+ assertThat(page.getNumberOfElements(), is(2));
+ assertThat(page, hasItems(carter, stefan));
+ }
+
+ @Test
+ public void findsPersonInAgeRangeCorrectly() throws Exception {
+
+ List result = repository.findByAgeBetween(40, 45);
+ assertThat(result.size(), is(2));
+ assertThat(result, hasItems(dave, leroi));
+ }
+
+ @Test
public void findsPersonByShippingAddressesCorrectly() throws Exception {
-
- Address address = new Address("Foo Street 1", "C0123", "Bar");
- dave.setShippingAddresses(new HashSet(asList(address)));
-
- repository.save(dave);
- assertThat(repository.findByShippingAddresses(address), is(dave));
+
+ Address address = new Address("Foo Street 1", "C0123", "Bar");
+ dave.setShippingAddresses(new HashSet(asList(address)));
+
+ repository.save(dave);
+ assertThat(repository.findByShippingAddresses(address), is(dave));
}
-
- @Test
+
+ @Test
public void findsPersonByAddressCorrectly() throws Exception {
-
- Address address = new Address("Foo Street 1", "C0123", "Bar");
- dave.setAddress(address);
- repository.save(dave);
-
- List result = repository.findByAddress(address);
- assertThat(result.size(), is(1));
+
+ Address address = new Address("Foo Street 1", "C0123", "Bar");
+ dave.setAddress(address);
+ repository.save(dave);
+
+ List result = repository.findByAddress(address);
+ assertThat(result.size(), is(1));
assertThat(result, hasItem(dave));
}
-
- @Test
+
+ @Test
public void findsPeopleByZipCode() throws Exception {
-
- Address address = new Address("Foo Street 1", "C0123", "Bar");
- dave.setAddress(address);
- repository.save(dave);
-
- List result = repository.findByAddressZipCode(address.getZipCode());
- assertThat(result.size(), is(1));
+
+ Address address = new Address("Foo Street 1", "C0123", "Bar");
+ dave.setAddress(address);
+ repository.save(dave);
+
+ List result = repository.findByAddressZipCode(address.getZipCode());
+ assertThat(result.size(), is(1));
assertThat(result, hasItem(dave));
}
}
\ No newline at end of file
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/MongoQueryCreatorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/MongoQueryCreatorUnitTests.java
index ec08d16bb..bb92ca28f 100644
--- a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/MongoQueryCreatorUnitTests.java
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/MongoQueryCreatorUnitTests.java
@@ -15,6 +15,8 @@
*/
package org.springframework.data.document.mongodb.repository;
+import static org.springframework.data.document.mongodb.repository.StubParameterAccessor.*;
+
import java.lang.reflect.Method;
import java.util.List;
@@ -25,8 +27,6 @@ import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.data.document.mongodb.MongoConverter;
import org.springframework.data.document.mongodb.Person;
-import org.springframework.data.repository.query.Parameters;
-import org.springframework.data.repository.query.SimpleParameterAccessor;
import org.springframework.data.repository.query.parser.PartTree;
@@ -63,17 +63,13 @@ public class MongoQueryCreatorUnitTests {
PartTree tree = new PartTree("findByFirstName", Person.class);
MongoQueryCreator creator =
- new MongoQueryCreator(tree, new SimpleParameterAccessor(
- new Parameters(findByFirstname),
- new Object[] { "Oliver" }), converter);
+ new MongoQueryCreator(tree, getAccessor(converter, "Oliver"));
creator.createQuery();
creator =
new MongoQueryCreator(new PartTree("findByFirstNameAndFriend",
- Person.class), new SimpleParameterAccessor(
- new Parameters(findByFirstnameAndFriend), new Object[] {
- "Oliver", new Person() }), converter);
+ Person.class), getAccessor(converter, "Oliver", new Person()));
creator.createQuery();
}
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/PersonRepository.java b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/PersonRepository.java
index 3af1be0b3..d9a0752db 100644
--- a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/PersonRepository.java
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/PersonRepository.java
@@ -35,6 +35,16 @@ public interface PersonRepository extends MongoRepository {
* @return
*/
List findByLastname(String lastname);
+
+ /**
+ * Returns the {@link Person}s with the given firstname. Uses {@link Query} annotation to define the query to be
+ * executed.
+ *
+ * @param firstname
+ * @return
+ */
+ @Query("{ 'firstname' : ? }")
+ List findByThePersonsFirstname(String firstname);
/**
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/StringBasedMongoQueryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/StringBasedMongoQueryUnitTests.java
new file mode 100644
index 000000000..3072315a9
--- /dev/null
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/StringBasedMongoQueryUnitTests.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.data.document.mongodb.repository;
+
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.*;
+
+import java.lang.reflect.Method;
+
+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.data.document.mongodb.MongoConverter;
+import org.springframework.data.document.mongodb.MongoTemplate;
+import org.springframework.data.document.mongodb.SimpleMongoConverter;
+import org.springframework.data.document.mongodb.query.BasicQuery;
+
+/**
+ * Unit tests for {@link StringBasedMongoQuery}.
+ *
+ * @author Oliver Gierke
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class StringBasedMongoQueryUnitTests {
+
+ @Mock
+ MongoTemplate template;
+ MongoConverter converter = new SimpleMongoConverter();
+
+ @Before
+ public void setUp() {
+ when(template.getConverter()).thenReturn(converter);
+ }
+
+ @Test
+ public void testname() throws Exception {
+
+ Method method = SampleRepository.class.getMethod("findByLastname", String.class);
+ MongoQueryMethod queryMethod = new MongoQueryMethod(method);
+ StringBasedMongoQuery mongoQuery = new StringBasedMongoQuery(queryMethod, template);
+ ConvertingParameterAccessor accesor = StubParameterAccessor.getAccessor(converter, "Matthews");
+
+ org.springframework.data.document.mongodb.query.Query query = mongoQuery.createQuery(accesor);
+ org.springframework.data.document.mongodb.query.Query reference = new BasicQuery("{'lastname' : 'Matthews'}");
+
+ assertThat(query.getQueryObject(), is(reference.getQueryObject()));
+ }
+
+ private interface SampleRepository {
+
+ @Query("{ 'lastname' : ? }")
+ Person findByLastname(String lastname);
+ }
+}
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/StubParameterAccessor.java b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/StubParameterAccessor.java
new file mode 100644
index 000000000..83acc5cca
--- /dev/null
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/StubParameterAccessor.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.data.document.mongodb.repository;
+
+import java.util.Arrays;
+import java.util.Iterator;
+
+import org.springframework.data.document.mongodb.MongoWriter;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.repository.query.ParameterAccessor;
+
+/**
+ * Simple {@link ParameterAccessor} that returns the given parameters unfiltered.
+ *
+ * @author Oliver Gierke
+ */
+class StubParameterAccessor implements ParameterAccessor {
+
+ /**
+ * Creates a new {@link ConvertingParameterAccessor} backed by a {@link StubParameterAccessor} simply returning the
+ * given parameters converted but unfiltered.
+ *
+ * @param converter
+ * @param parameters
+ * @return
+ */
+ public static ConvertingParameterAccessor getAccessor(MongoWriter converter, Object... parameters) {
+
+ return new ConvertingParameterAccessor(converter, new StubParameterAccessor(parameters));
+ }
+
+ /**
+ *
+ */
+ private Object[] values;
+
+ public StubParameterAccessor(Object... values) {
+ this.values = values;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.springframework.data.repository.query.ParameterAccessor#getPageable()
+ */
+ public Pageable getPageable() {
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.springframework.data.repository.query.ParameterAccessor#getSort()
+ */
+ public Sort getSort() {
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Iterable#iterator()
+ */
+ public Iterator iterator() {
+ return Arrays.asList(values).iterator();
+ }
+}
\ No newline at end of file
diff --git a/spring-data-mongodb/template.mf b/spring-data-mongodb/template.mf
index 5f8a12d36..7cc16ff69 100644
--- a/spring-data-mongodb/template.mf
+++ b/spring-data-mongodb/template.mf
@@ -19,6 +19,7 @@ Import-Template:
org.bson.*;version="0",
org.aopalliance.*;version="[1.0.0, 2.0.0)";resolution:=optional,
org.apache.commons.logging.*;version="[1.1.1, 2.0.0)",
+ org.slf4j.*;version="[1.5.0,1.6.0)",
org.w3c.dom.*;version="0"