Browse Source

Added support for non-primitive-value-referencing queries.

Query methods can now query for related objects of an entity. Test cases are centered around a Person having an Address. The query is something like:

List<Person> findByAddress(Address address);

We correctly marshal the parameter into a DBObject using the MongoConverter on argument binding.

Exposed the configured MongoConverter at MongoTemplate so that the repository infrastructure gets access to it. Let repository classes work with the template again instead of plain MongoOperations. Removed find(…) method from MongoOperations and -Template. Extended SimpleMongoConverter so that it can unmarshal collections as well.
pull/1/head
Oliver Gierke 15 years ago
parent
commit
9152ca89da
  1. 10
      spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/MongoOperations.java
  2. 22
      spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/MongoTemplate.java
  3. 86
      spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/SimpleMongoConverter.java
  4. 22
      spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoQuery.java
  5. 44
      spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoQueryCreator.java
  6. 30
      spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoRepositoryFactoryBean.java
  7. 37
      spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/SimpleMongoRepository.java
  8. 2
      spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/config/MongoRepositoryConfigDefinitionParser.java
  9. 11
      spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/MongoTemplateTests.java
  10. 25
      spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java
  11. 84
      spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/Address.java
  12. 12
      spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/MongoQueryCreatorUnitTests.java
  13. 6
      spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/MongoRepositoryFactoryUnitTests.java
  14. 40
      spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/Person.java
  15. 18
      spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/PersonRepository.java
  16. 2
      spring-data-mongodb/src/test/resources/org/springframework/data/document/mongodb/repository/PersonRepositoryIntegrationTests-context.xml

10
spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/MongoOperations.java

@ -506,14 +506,4 @@ public interface MongoOperations { @@ -506,14 +506,4 @@ public interface MongoOperations {
* @return the List of converted objects.
*/
<T> List<T> query(String collectionName, DBObject query, Class<T> targetClass, MongoReader<T> reader);
/**
* Returns the object with the given id for the given target class.
*
* @param targetClass the type of the object to be retrieved
* @param id the id of the object to be retrieved
* @return the converted object
*/
<T> T find(Class<T> targetClass, Object id);
}

22
spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/MongoTemplate.java

@ -39,7 +39,6 @@ import com.mongodb.DBCursor; @@ -39,7 +39,6 @@ import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.Mongo;
import com.mongodb.MongoException;
import com.mongodb.QueryBuilder;
import com.mongodb.util.JSON;
/**
@ -125,6 +124,15 @@ public class MongoTemplate implements InitializingBean, MongoOperations { @@ -125,6 +124,15 @@ public class MongoTemplate implements InitializingBean, MongoOperations {
Assert.notNull(databaseName);
this.databaseName = databaseName;
}
/**
* Returns the default {@link MongoConverter}.
*
* @return
*/
public MongoConverter getConverter() {
return this.mongoConverter;
}
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.MongoOperations#getDefaultCollectionName()
@ -634,18 +642,6 @@ public class MongoTemplate implements InitializingBean, MongoOperations { @@ -634,18 +642,6 @@ public class MongoTemplate implements InitializingBean, MongoOperations {
return executeEach(new FindCallback(query), null, new ReadDbObjectCallback<T>(reader, targetClass),
collectionName);
}
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.MongoOperations#find(java.lang.Class, java.lang.Object)
*/
public <T> T find(Class<T> targetClass, Object id) {
ObjectId objectId = mongoConverter.convertObjectId(id);
List<T> result = query(QueryBuilder.start(MongoPropertyDescriptor.ID_KEY).is(objectId).get(), targetClass);
return result.isEmpty() ? null : result.get(0);
}
public DB getDb() {

86
spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/SimpleMongoConverter.java

@ -22,6 +22,7 @@ import java.lang.reflect.Type; @@ -22,6 +22,7 @@ import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@ -38,6 +39,7 @@ import org.apache.commons.logging.LogFactory; @@ -38,6 +39,7 @@ import org.apache.commons.logging.LogFactory;
import org.bson.types.CodeWScope;
import org.bson.types.ObjectId;
import org.springframework.beans.BeanUtils;
import org.springframework.core.CollectionFactory;
import org.springframework.core.convert.ConversionFailedException;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.converter.Converter;
@ -47,6 +49,7 @@ import org.springframework.data.document.mongodb.MongoPropertyDescriptors.MongoP @@ -47,6 +49,7 @@ import org.springframework.data.document.mongodb.MongoPropertyDescriptors.MongoP
import org.springframework.util.Assert;
import org.springframework.util.comparator.CompoundComparator;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import com.mongodb.DBRef;
@ -163,8 +166,8 @@ public class SimpleMongoConverter implements MongoConverter { @@ -163,8 +166,8 @@ public class SimpleMongoConverter implements MongoConverter {
for (MongoPropertyDescriptor descriptor : beanWrapper.getDescriptors()) {
if (descriptor.isMappable()) {
Object value = beanWrapper.getValue(descriptor);
if(value == null) {
if (value == null) {
continue;
}
@ -315,26 +318,13 @@ public class SimpleMongoConverter implements MongoConverter { @@ -315,26 +318,13 @@ public class SimpleMongoConverter implements MongoConverter {
if (descriptor.isMappable()) {
Object value = source.get(keyToUse);
if (!isSimpleType(value.getClass())) {
if (value instanceof DBObject) {
if (value instanceof Object[]) {
bw.setValue(descriptor, readCollection(descriptor, Arrays.asList((Object[]) value))
.toArray());
} else if (value instanceof BasicDBList) {
bw.setValue(descriptor, readCollection(descriptor, (BasicDBList) value));
} else if (value instanceof DBObject) {
bw.setValue(descriptor, readCompoundValue(descriptor, (DBObject) value));
} else if (value instanceof Object[]) {
Object[] values = new Object[((Object[]) value).length];
int i = 0;
for (Object o : (Object[]) value) {
if (o instanceof DBObject) {
Class<?> type;
if (descriptor.getPropertyType().isArray()) {
type = descriptor.getPropertyType().getComponentType();
} else {
type = getGenericParameters(descriptor.getTypeToSet()).get(0);
}
values[i] = read(type, (DBObject) o);
} else {
values[i] = o;
}
i++;
}
bw.setValue(descriptor, values);
} else {
LOG.warn("Unable to map compound DBObject field " + keyToUse + " to property "
+ descriptor.getName()
@ -355,7 +345,41 @@ public class SimpleMongoConverter implements MongoConverter { @@ -355,7 +345,41 @@ public class SimpleMongoConverter implements MongoConverter {
}
/**
* Reads a compund value from the given {@link DBObject} for the given property.
* Reads the given collection values (that are {@link DBObject}s potentially) into a {@link Collection} of domain
* objects.
*
* @param descriptor
* @param values
* @return
*/
private Collection<Object> readCollection(MongoPropertyDescriptor descriptor, Collection<?> values) {
Class<?> targetCollectionType = descriptor.getPropertyType();
boolean targetIsArray = targetCollectionType.isArray();
@SuppressWarnings("unchecked")
Collection<Object> result = targetIsArray ? new ArrayList<Object>(values.size()) : CollectionFactory
.createCollection(targetCollectionType, values.size());
for (Object o : values) {
if (o instanceof DBObject) {
Class<?> type;
if (targetIsArray) {
type = targetCollectionType.getComponentType();
} else {
type = getGenericParameters(descriptor.getTypeToSet()).get(0);
}
result.add(read(type, (DBObject) o));
} else {
result.add(o);
}
}
return result;
}
/**
* Reads a compound value from the given {@link DBObject} for the given property.
*
* @param pd
* @param dbo
@ -363,10 +387,10 @@ public class SimpleMongoConverter implements MongoConverter { @@ -363,10 +387,10 @@ public class SimpleMongoConverter implements MongoConverter {
*/
private Object readCompoundValue(MongoPropertyDescriptors.MongoPropertyDescriptor pd, DBObject dbo) {
Assert.isTrue(!pd.isCollection(), "Collections not supported!");
if (pd.isMap()) {
return readMap(pd, (BasicDBObject) dbo, getGenericParameters(pd.getTypeToSet()).get(1));
} else if (pd.isCollection()) {
throw new UnsupportedOperationException("Reading nested collections not supported yet!");
return readMap(pd, dbo, getGenericParameters(pd.getTypeToSet()).get(1));
} else {
return read(pd.getPropertyType(), dbo);
}
@ -390,16 +414,16 @@ public class SimpleMongoConverter implements MongoConverter { @@ -390,16 +414,16 @@ public class SimpleMongoConverter implements MongoConverter {
* @param targetType
* @return
*/
protected Map<?, ?> readMap(MongoPropertyDescriptors.MongoPropertyDescriptor pd, BasicDBObject dbo, Class<?> targetType) {
protected Map<?, ?> readMap(MongoPropertyDescriptors.MongoPropertyDescriptor pd, DBObject dbo, Class<?> targetType) {
Map<String, Object> map = createMap();
for (Entry<String, Object> entry : dbo.entrySet()) {
Object entryValue = entry.getValue();
if (!isSimpleType(entryValue.getClass())) {
map.put(entry.getKey(), read(targetType, (DBObject) entryValue));
for (String key : dbo.keySet()) {
Object value = dbo.get(key);
if (!isSimpleType(value.getClass())) {
map.put(key, read(targetType, (DBObject) value));
// Can do some reflection tricks here -
// throw new RuntimeException("User types not supported yet as values for Maps");
} else {
map.put(entry.getKey(), conversionService.convert(entryValue, targetType));
map.put(key, conversionService.convert(value, targetType));
}
}
return map;

22
spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoQuery.java

@ -20,7 +20,7 @@ import static org.springframework.data.document.mongodb.repository.MongoCursorUt @@ -20,7 +20,7 @@ import static org.springframework.data.document.mongodb.repository.MongoCursorUt
import java.util.List;
import org.springframework.data.document.mongodb.CollectionCallback;
import org.springframework.data.document.mongodb.MongoOperations;
import org.springframework.data.document.mongodb.MongoTemplate;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.query.QueryMethod;
@ -42,24 +42,24 @@ import com.mongodb.DBObject; @@ -42,24 +42,24 @@ import com.mongodb.DBObject;
public class MongoQuery implements RepositoryQuery {
private final QueryMethod method;
private final MongoOperations operations;
private final MongoTemplate template;
private final PartTree tree;
/**
* Creates a new {@link MongoQuery} from the given {@link QueryMethod} and
* {@link MongoOperations}.
* {@link MongoTemplate}.
*
* @param method
* @param operations
* @param template
*/
public MongoQuery(QueryMethod method, MongoOperations operations) {
public MongoQuery(QueryMethod method, MongoTemplate template) {
Assert.notNull(operations);
Assert.notNull(template);
Assert.notNull(method);
this.method = method;
this.operations = operations;
this.template = template;
this.tree = new PartTree(method.getName(), method.getDomainClass());
}
@ -75,7 +75,7 @@ public class MongoQuery implements RepositoryQuery { @@ -75,7 +75,7 @@ public class MongoQuery implements RepositoryQuery {
SimpleParameterAccessor accessor =
new SimpleParameterAccessor(method.getParameters(), parameters);
MongoQueryCreator creator = new MongoQueryCreator(tree, accessor);
MongoQueryCreator creator = new MongoQueryCreator(tree, accessor, template.getConverter());
DBObject query = creator.createQuery();
if (method.isCollectionQuery()) {
@ -95,7 +95,7 @@ public class MongoQuery implements RepositoryQuery { @@ -95,7 +95,7 @@ public class MongoQuery implements RepositoryQuery {
protected List<?> readCollection(DBObject query) {
return operations.query(operations.getDefaultCollectionName(),
return template.query(template.getDefaultCollectionName(),
query, method.getDomainClass());
}
}
@ -159,7 +159,7 @@ public class MongoQuery implements RepositoryQuery { @@ -159,7 +159,7 @@ public class MongoQuery implements RepositoryQuery {
int count = getCollectionCursor(creator.createQuery()).count();
List<?> result =
operations.query(query, method.getDomainClass(),
template.query(query, method.getDomainClass(),
withPagination(pageable));
return new PageImpl(result, pageable, count);
@ -168,7 +168,7 @@ public class MongoQuery implements RepositoryQuery { @@ -168,7 +168,7 @@ public class MongoQuery implements RepositoryQuery {
private DBCursor getCollectionCursor(final DBObject query) {
return operations.execute(new CollectionCallback<DBCursor>() {
return template.execute(new CollectionCallback<DBCursor>() {
public DBCursor doInCollection(DBCollection collection) {

44
spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoQueryCreator.java

@ -17,6 +17,7 @@ package org.springframework.data.document.mongodb.repository; @@ -17,6 +17,7 @@ package org.springframework.data.document.mongodb.repository;
import java.util.regex.Pattern;
import org.springframework.data.document.mongodb.MongoConverter;
import org.springframework.data.domain.Sort;
import org.springframework.data.repository.query.SimpleParameterAccessor;
import org.springframework.data.repository.query.SimpleParameterAccessor.BindableParameterIterator;
@ -25,6 +26,7 @@ import org.springframework.data.repository.query.parser.Part; @@ -25,6 +26,7 @@ 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;
import com.mongodb.QueryBuilder;
@ -35,6 +37,8 @@ import com.mongodb.QueryBuilder; @@ -35,6 +37,8 @@ import com.mongodb.QueryBuilder;
* @author Oliver Gierke
*/
class MongoQueryCreator extends AbstractQueryCreator<DBObject, QueryBuilder> {
private final MongoConverter converter;
/**
* Creates a new {@link MongoQueryCreator} from the given {@link PartTree}
@ -43,9 +47,10 @@ class MongoQueryCreator extends AbstractQueryCreator<DBObject, QueryBuilder> { @@ -43,9 +47,10 @@ class MongoQueryCreator extends AbstractQueryCreator<DBObject, QueryBuilder> {
* @param tree
* @param accessor
*/
public MongoQueryCreator(PartTree tree, SimpleParameterAccessor accessor) {
public MongoQueryCreator(PartTree tree, SimpleParameterAccessor accessor, MongoConverter converter) {
super(tree, accessor);
this.converter = converter;
}
@ -125,11 +130,11 @@ class MongoQueryCreator extends AbstractQueryCreator<DBObject, QueryBuilder> { @@ -125,11 +130,11 @@ class MongoQueryCreator extends AbstractQueryCreator<DBObject, QueryBuilder> {
switch (type) {
case GREATER_THAN:
return criteria.greaterThan(parameters.next());
return criteria.greaterThan(getConvertedParameter(parameters));
case LESS_THAN:
return criteria.lessThan(parameters.next());
return criteria.lessThan(getConvertedParameter(parameters));
case BETWEEN:
return criteria.greaterThan(parameters.next()).lessThan(parameters.next());
return criteria.greaterThan(getConvertedParameter(parameters)).lessThan(getConvertedParameter(parameters));
case IS_NOT_NULL:
return criteria.notEquals(null);
case IS_NULL:
@ -138,13 +143,21 @@ class MongoQueryCreator extends AbstractQueryCreator<DBObject, QueryBuilder> { @@ -138,13 +143,21 @@ class MongoQueryCreator extends AbstractQueryCreator<DBObject, QueryBuilder> {
String value = parameters.next().toString();
return criteria.regex(toLikeRegex(value));
case SIMPLE_PROPERTY:
return criteria.is(parameters.next());
return criteria.is(getConvertedParameter(parameters));
case NEGATING_SIMPLE_PROPERTY:
return criteria.notEquals(parameters.next());
return criteria.notEquals(getConvertedParameter(parameters));
}
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) {
@ -152,4 +165,23 @@ class MongoQueryCreator extends AbstractQueryCreator<DBObject, QueryBuilder> { @@ -152,4 +165,23 @@ class MongoQueryCreator extends AbstractQueryCreator<DBObject, QueryBuilder> {
String regex = source.replaceAll("\\*", ".*");
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;
}
}
}

30
spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoRepositoryFactoryBean.java

@ -18,8 +18,8 @@ package org.springframework.data.document.mongodb.repository; @@ -18,8 +18,8 @@ package org.springframework.data.document.mongodb.repository;
import java.io.Serializable;
import java.lang.reflect.Method;
import org.springframework.data.document.mongodb.MongoOperations;
import org.springframework.data.document.mongodb.MongoPropertyDescriptors.MongoPropertyDescriptor;
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;
@ -41,17 +41,17 @@ import org.springframework.util.StringUtils; @@ -41,17 +41,17 @@ import org.springframework.util.StringUtils;
public class MongoRepositoryFactoryBean extends
RepositoryFactoryBeanSupport<MongoRepository<?, ?>> {
private MongoOperations operations;
private MongoTemplate template;
/**
* Configures the {@link MongoOperations} to be used.
* Configures the {@link MongoTemplate} to be used.
*
* @param operations the template to set
* @param template the template to set
*/
public void setOperations(MongoOperations operations) {
public void setTemplate(MongoTemplate template) {
this.operations = operations;
this.template = template;
}
@ -65,7 +65,7 @@ public class MongoRepositoryFactoryBean extends @@ -65,7 +65,7 @@ public class MongoRepositoryFactoryBean extends
@Override
protected RepositoryFactorySupport createRepositoryFactory() {
return new MongoRepositoryFactory(operations);
return new MongoRepositoryFactory(template);
}
@ -80,7 +80,7 @@ public class MongoRepositoryFactoryBean extends @@ -80,7 +80,7 @@ public class MongoRepositoryFactoryBean extends
public void afterPropertiesSet() {
super.afterPropertiesSet();
Assert.notNull(operations, "MongoTemplate must not be null!");
Assert.notNull(template, "MongoTemplate must not be null!");
}
/**
@ -90,16 +90,16 @@ public class MongoRepositoryFactoryBean extends @@ -90,16 +90,16 @@ public class MongoRepositoryFactoryBean extends
*/
public static class MongoRepositoryFactory extends RepositoryFactorySupport {
private final MongoOperations operations;
private final MongoTemplate template;
/**
* Creates a new {@link MongoRepositoryFactory} fwith the given {@link MongoOperations}.
* Creates a new {@link MongoRepositoryFactory} fwith the given {@link MongoTemplate}.
*
* @param operations
* @param template
*/
public MongoRepositoryFactory(MongoOperations operations) {
public MongoRepositoryFactory(MongoTemplate template) {
this.operations = operations;
this.template = template;
}
@ -107,7 +107,7 @@ public class MongoRepositoryFactoryBean extends @@ -107,7 +107,7 @@ public class MongoRepositoryFactoryBean extends
protected <T, ID extends Serializable> RepositorySupport<T, ID> getTargetRepository(
Class<T> domainClass, Class<?> repositoryInterface) {
return new SimpleMongoRepository<T, ID>(domainClass, operations);
return new SimpleMongoRepository<T, ID>(domainClass, template);
}
@ -134,7 +134,7 @@ public class MongoRepositoryFactoryBean extends @@ -134,7 +134,7 @@ public class MongoRepositoryFactoryBean extends
public RepositoryQuery resolveQuery(Method method) {
return new MongoQuery(new QueryMethod(method), operations);
return new MongoQuery(new QueryMethod(method), template);
}
}

37
spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/SimpleMongoRepository.java

@ -21,7 +21,8 @@ import java.io.Serializable; @@ -21,7 +21,8 @@ import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import org.springframework.data.document.mongodb.MongoOperations;
import org.springframework.data.document.mongodb.MongoConverter;
import org.springframework.data.document.mongodb.MongoTemplate;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
@ -43,24 +44,24 @@ import com.mongodb.QueryBuilder; @@ -43,24 +44,24 @@ import com.mongodb.QueryBuilder;
public class SimpleMongoRepository<T, ID extends Serializable> extends
RepositorySupport<T, ID> implements PagingAndSortingRepository<T, ID> {
private final MongoOperations operations;
private final MongoTemplate template;
private MongoEntityInformation entityInformation;
/**
* Creates a ew {@link SimpleMongoRepository} for the given domain class and
* {@link MongoOperations}.
* {@link MongoTemplate}.
*
* @param domainClass
* @param operations
* @param template
*/
public SimpleMongoRepository(Class<T> domainClass,
MongoOperations operations) {
MongoTemplate template) {
super(domainClass);
Assert.notNull(operations);
this.operations = operations;
Assert.notNull(template);
this.template = template;
}
@ -72,7 +73,7 @@ public class SimpleMongoRepository<T, ID extends Serializable> extends @@ -72,7 +73,7 @@ public class SimpleMongoRepository<T, ID extends Serializable> extends
*/
public T save(T entity) {
operations.save(entity);
template.save(entity);
return entity;
}
@ -88,7 +89,7 @@ public class SimpleMongoRepository<T, ID extends Serializable> extends @@ -88,7 +89,7 @@ public class SimpleMongoRepository<T, ID extends Serializable> extends
List<T> result = new ArrayList<T>();
for (T entity : entities) {
operations.save(entity);
template.save(entity);
result.add(entity);
}
@ -105,7 +106,11 @@ public class SimpleMongoRepository<T, ID extends Serializable> extends @@ -105,7 +106,11 @@ public class SimpleMongoRepository<T, ID extends Serializable> extends
*/
public T findById(ID id) {
return operations.find(getDomainClass(), id);
MongoConverter converter = template.getConverter();
List<T> result = template.query(QueryBuilder.start("_id").is(converter.convertObjectId(id)).get(),
getDomainClass());
return result.isEmpty() ? null : result.get(0);
}
@ -129,7 +134,7 @@ public class SimpleMongoRepository<T, ID extends Serializable> extends @@ -129,7 +134,7 @@ public class SimpleMongoRepository<T, ID extends Serializable> extends
*/
public List<T> findAll() {
return operations.getCollection(getDomainClass());
return template.getCollection(getDomainClass());
}
@ -140,7 +145,7 @@ public class SimpleMongoRepository<T, ID extends Serializable> extends @@ -140,7 +145,7 @@ public class SimpleMongoRepository<T, ID extends Serializable> extends
*/
public Long count() {
return operations.getCollection(operations.getDefaultCollectionName())
return template.getCollection(template.getDefaultCollectionName())
.count();
}
@ -156,7 +161,7 @@ public class SimpleMongoRepository<T, ID extends Serializable> extends @@ -156,7 +161,7 @@ public class SimpleMongoRepository<T, ID extends Serializable> extends
QueryBuilder builder =
QueryBuilder.start(entityInformation.getFieldName()).is(
entityInformation.getId(entity));
operations.remove(builder.get());
template.remove(builder.get());
}
@ -181,7 +186,7 @@ public class SimpleMongoRepository<T, ID extends Serializable> extends @@ -181,7 +186,7 @@ public class SimpleMongoRepository<T, ID extends Serializable> extends
*/
public void deleteAll() {
operations.dropCollection(operations.getDefaultCollectionName());
template.dropCollection(template.getDefaultCollectionName());
}
@ -197,7 +202,7 @@ public class SimpleMongoRepository<T, ID extends Serializable> extends @@ -197,7 +202,7 @@ public class SimpleMongoRepository<T, ID extends Serializable> extends
Long count = count();
List<T> list =
operations.query(new BasicDBObject(), getDomainClass(),
template.query(new BasicDBObject(), getDomainClass(),
withPagination(pageable));
return new PageImpl<T>(list, pageable, count);
@ -213,7 +218,7 @@ public class SimpleMongoRepository<T, ID extends Serializable> extends @@ -213,7 +218,7 @@ public class SimpleMongoRepository<T, ID extends Serializable> extends
*/
public List<T> findAll(final Sort sort) {
return operations.query(new BasicDBObject(), getDomainClass(),
return template.query(new BasicDBObject(), getDomainClass(),
withSorting(sort));
}

2
spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/config/MongoRepositoryConfigDefinitionParser.java

@ -46,6 +46,6 @@ public class MongoRepositoryConfigDefinitionParser @@ -46,6 +46,6 @@ public class MongoRepositoryConfigDefinitionParser
MongoRepositoryConfiguration context,
BeanDefinitionBuilder builder, Object beanSource) {
builder.addPropertyReference("operations", context.getMongoTemplateRef());
builder.addPropertyReference("template", context.getMongoTemplateRef());
}
}

11
spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/MongoTemplateTests.java

@ -18,6 +18,8 @@ package org.springframework.data.document.mongodb; @@ -18,6 +18,8 @@ package org.springframework.data.document.mongodb;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -25,6 +27,8 @@ import org.springframework.beans.factory.annotation.Autowired; @@ -25,6 +27,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.mongodb.QueryBuilder;
/**
* Integration test for {@link MongoTemplate}.
*
@ -47,8 +51,11 @@ public class MongoTemplateTests { @@ -47,8 +51,11 @@ public class MongoTemplateTests {
Person person = new Person("Oliver");
template.insert(person);
MongoConverter converter = template.getConverter();
Person reference = template.find(Person.class, person.getId());
assertThat(reference, is(person));
List<Person> result = template.query(QueryBuilder.start("_id").is(converter.convertObjectId(person.getId())).get(), Person.class);
assertThat(result.size(), is(1));
assertThat(result, hasItem(person));
}
}

25
spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java

@ -1,9 +1,11 @@ @@ -1,9 +1,11 @@
package org.springframework.data.document.mongodb.repository;
import static java.util.Arrays.*;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import org.junit.Before;
@ -94,4 +96,27 @@ public abstract class AbstractPersonRepositoryIntegrationTests { @@ -94,4 +96,27 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
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<Address>(asList(address)));
repository.save(dave);
assertThat(repository.findByShippingAddresses(address), is(dave));
}
@Test
public void findsPersonByAddressCorrectly() throws Exception {
Address address = new Address("Foo Street 1", "C0123", "Bar");
dave.setAddress(address);
repository.save(dave);
List<Person> result = repository.findByAddress(address);
assertThat(result.size(), is(1));
assertThat(result, hasItem(dave));
}
}

84
spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/Address.java

@ -0,0 +1,84 @@ @@ -0,0 +1,84 @@
/*
* 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;
/**
*
* @author Oliver Gierke
*/
public class Address {
private String street;
private String zipCode;
private String city;
protected Address() {
}
/**
* @param string
* @param string2
* @param string3
*/
public Address(String street, String zipcode, String city) {
this.street = street;
this.zipCode = zipcode;
this.city = city;
}
/**
* @return the street
*/
public String getStreet() {
return street;
}
/**
* @param street the street to set
*/
public void setStreet(String street) {
this.street = street;
}
/**
* @return the zipCode
*/
public String getZipCode() {
return zipCode;
}
/**
* @param zipCode the zipCode to set
*/
public void setZipCode(String zipCode) {
this.zipCode = zipCode;
}
/**
* @return the city
*/
public String getCity() {
return city;
}
/**
* @param city the city to set
*/
public void setCity(String city) {
this.city = city;
}
}

12
spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/MongoQueryCreatorUnitTests.java

@ -20,6 +20,10 @@ import java.util.List; @@ -20,6 +20,10 @@ import java.util.List;
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.Person;
import org.springframework.data.repository.query.Parameters;
import org.springframework.data.repository.query.SimpleParameterAccessor;
@ -31,10 +35,14 @@ import org.springframework.data.repository.query.parser.PartTree; @@ -31,10 +35,14 @@ import org.springframework.data.repository.query.parser.PartTree;
*
* @author Oliver Gierke
*/
@RunWith(MockitoJUnitRunner.class)
public class MongoQueryCreatorUnitTests {
Method findByFirstname;
Method findByFirstnameAndFriend;
@Mock
MongoConverter converter;
@Before
@ -57,7 +65,7 @@ public class MongoQueryCreatorUnitTests { @@ -57,7 +65,7 @@ public class MongoQueryCreatorUnitTests {
MongoQueryCreator creator =
new MongoQueryCreator(tree, new SimpleParameterAccessor(
new Parameters(findByFirstname),
new Object[] { "Oliver" }));
new Object[] { "Oliver" }), converter);
creator.createQuery();
@ -65,7 +73,7 @@ public class MongoQueryCreatorUnitTests { @@ -65,7 +73,7 @@ public class MongoQueryCreatorUnitTests {
new MongoQueryCreator(new PartTree("findByFirstnameAndFriend",
Person.class), new SimpleParameterAccessor(
new Parameters(findByFirstnameAndFriend), new Object[] {
"Oliver", new Person() }));
"Oliver", new Person() }), converter);
creator.createQuery();
}

6
spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/MongoRepositoryFactoryUnitTests.java

@ -19,7 +19,7 @@ import org.junit.Test; @@ -19,7 +19,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.data.document.mongodb.MongoOperations;
import org.springframework.data.document.mongodb.MongoTemplate;
import org.springframework.data.document.mongodb.User;
import org.springframework.data.document.mongodb.repository.MongoRepositoryFactoryBean.MongoRepositoryFactory;
@ -32,11 +32,11 @@ import org.springframework.data.document.mongodb.repository.MongoRepositoryFacto @@ -32,11 +32,11 @@ import org.springframework.data.document.mongodb.repository.MongoRepositoryFacto
public class MongoRepositoryFactoryUnitTests {
@Mock
MongoOperations operations;
MongoTemplate template;
@Test(expected = IllegalArgumentException.class)
public void rejectsInvalidIdType() throws Exception {
MongoRepositoryFactory factory = new MongoRepositoryFactory(operations);
MongoRepositoryFactory factory = new MongoRepositoryFactory(template);
factory.getRepository(SampleRepository.class);
}

40
spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/Person.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2010-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -15,6 +15,8 @@ @@ -15,6 +15,8 @@
*/
package org.springframework.data.document.mongodb.repository;
import java.util.Set;
import org.bson.types.ObjectId;
@ -29,9 +31,12 @@ public class Person { @@ -29,9 +31,12 @@ public class Person {
private String firstname;
private String lastname;
private Integer age;
private Address address;
private Set<Address> shippingAddresses;
public Person() {
public Person() {
this(null, null);
}
@ -122,6 +127,37 @@ public class Person { @@ -122,6 +127,37 @@ public class Person {
this.age = age;
}
/**
* @return the address
*/
public Address getAddress() {
return address;
}
/**
* @param address the address to set
*/
public void setAddress(Address address) {
this.address = address;
}
/**
* @return the addresses
*/
public Set<Address> getShippingAddresses() {
return shippingAddresses;
}
/**
* @param addresses the addresses to set
*/
public void setShippingAddresses(Set<Address> addresses) {
this.shippingAddresses = addresses;
}
/*

18
spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/PersonRepository.java

@ -66,4 +66,22 @@ public interface PersonRepository extends MongoRepository<Person, String> { @@ -66,4 +66,22 @@ public interface PersonRepository extends MongoRepository<Person, String> {
* @return
*/
List<Person> findByAgeBetween(int from, int to);
/**
* Returns the {@link Person} with the given {@link Address} as shipping address.
*
* @param address
* @return
*/
Person findByShippingAddresses(Address address);
/**
* Returns all {@link Person}s with the given {@link Address}.
*
* @param address
* @return
*/
List<Person> findByAddress(Address address);
}

2
spring-data-mongodb/src/test/resources/org/springframework/data/document/mongodb/repository/PersonRepositoryIntegrationTests-context.xml

@ -6,7 +6,7 @@ @@ -6,7 +6,7 @@
<import resource="classpath:infrastructure.xml" />
<bean class="org.springframework.data.document.mongodb.repository.MongoRepositoryFactoryBean">
<property name="operations" ref="mongoTemplate" />
<property name="template" ref="mongoTemplate" />
<property name="repositoryInterface" value="org.springframework.data.document.mongodb.repository.PersonRepository" />
</bean>

Loading…
Cancel
Save