From 9152ca89da015ab931ecd1a83da77151a97444b7 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Fri, 7 Jan 2011 16:44:49 +0100 Subject: [PATCH] Added support for non-primitive-value-referencing queries. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 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. --- .../document/mongodb/MongoOperations.java | 10 --- .../data/document/mongodb/MongoTemplate.java | 22 ++--- .../mongodb/SimpleMongoConverter.java | 86 ++++++++++++------- .../mongodb/repository/MongoQuery.java | 22 ++--- .../mongodb/repository/MongoQueryCreator.java | 44 ++++++++-- .../MongoRepositoryFactoryBean.java | 30 +++---- .../repository/SimpleMongoRepository.java | 37 ++++---- ...MongoRepositoryConfigDefinitionParser.java | 2 +- .../document/mongodb/MongoTemplateTests.java | 11 ++- ...tractPersonRepositoryIntegrationTests.java | 25 ++++++ .../document/mongodb/repository/Address.java | 84 ++++++++++++++++++ .../MongoQueryCreatorUnitTests.java | 12 ++- .../MongoRepositoryFactoryUnitTests.java | 6 +- .../document/mongodb/repository/Person.java | 40 ++++++++- .../mongodb/repository/PersonRepository.java | 18 ++++ ...rsonRepositoryIntegrationTests-context.xml | 2 +- 16 files changed, 338 insertions(+), 113 deletions(-) create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/Address.java diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/MongoOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/MongoOperations.java index 7407cc7b1..e0cf1b6a6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/MongoOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/MongoOperations.java @@ -506,14 +506,4 @@ public interface MongoOperations { * @return the List of converted objects. */ List query(String collectionName, DBObject query, Class targetClass, MongoReader 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 find(Class targetClass, Object id); } \ No newline at end of file diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/MongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/MongoTemplate.java index c125c920a..e2e6b3ef3 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/MongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/MongoTemplate.java @@ -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 { 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 { return executeEach(new FindCallback(query), null, new ReadDbObjectCallback(reader, targetClass), collectionName); } - - - /* (non-Javadoc) - * @see org.springframework.data.document.mongodb.MongoOperations#find(java.lang.Class, java.lang.Object) - */ - public T find(Class targetClass, Object id) { - - ObjectId objectId = mongoConverter.convertObjectId(id); - List result = query(QueryBuilder.start(MongoPropertyDescriptor.ID_KEY).is(objectId).get(), targetClass); - - return result.isEmpty() ? null : result.get(0); - } public DB getDb() { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/SimpleMongoConverter.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/SimpleMongoConverter.java index 516888f7e..2fe089e5e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/SimpleMongoConverter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/SimpleMongoConverter.java @@ -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; 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 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 { 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 { 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 { } /** - * 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 readCollection(MongoPropertyDescriptor descriptor, Collection values) { + + Class targetCollectionType = descriptor.getPropertyType(); + boolean targetIsArray = targetCollectionType.isArray(); + + @SuppressWarnings("unchecked") + Collection result = targetIsArray ? new ArrayList(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 { */ 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 { * @param targetType * @return */ - protected Map readMap(MongoPropertyDescriptors.MongoPropertyDescriptor pd, BasicDBObject dbo, Class targetType) { + protected Map readMap(MongoPropertyDescriptors.MongoPropertyDescriptor pd, DBObject dbo, Class targetType) { Map map = createMap(); - for (Entry 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; 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/MongoQuery.java index c6f6a30e4..80013f2b1 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/MongoQuery.java @@ -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; 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 { 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 { 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 { 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 { private DBCursor getCollectionCursor(final DBObject query) { - return operations.execute(new CollectionCallback() { + return template.execute(new CollectionCallback() { public DBCursor doInCollection(DBCollection collection) { 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 434bb14d3..b0be6a50a 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 @@ -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; 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; * @author Oliver Gierke */ class MongoQueryCreator extends AbstractQueryCreator { + + private final MongoConverter converter; /** * Creates a new {@link MongoQueryCreator} from the given {@link PartTree} @@ -43,9 +47,10 @@ class MongoQueryCreator extends AbstractQueryCreator { * @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 { 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 { 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 { 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; + } + } } \ No newline at end of file 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 f4260b2f7..c9b9cc7c0 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 @@ -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; public class MongoRepositoryFactoryBean extends RepositoryFactoryBeanSupport> { - 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 @Override protected RepositoryFactorySupport createRepositoryFactory() { - return new MongoRepositoryFactory(operations); + return new MongoRepositoryFactory(template); } @@ -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 */ 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 protected RepositorySupport getTargetRepository( Class domainClass, Class repositoryInterface) { - return new SimpleMongoRepository(domainClass, operations); + return new SimpleMongoRepository(domainClass, template); } @@ -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); } } 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 5223ffcb3..c69af05cd 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 @@ -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; public class SimpleMongoRepository extends RepositorySupport implements PagingAndSortingRepository { - 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 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 extends */ public T save(T entity) { - operations.save(entity); + template.save(entity); return entity; } @@ -88,7 +89,7 @@ public class SimpleMongoRepository extends List result = new ArrayList(); for (T entity : entities) { - operations.save(entity); + template.save(entity); result.add(entity); } @@ -105,7 +106,11 @@ public class SimpleMongoRepository extends */ public T findById(ID id) { - return operations.find(getDomainClass(), id); + MongoConverter converter = template.getConverter(); + + List 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 extends */ public List findAll() { - return operations.getCollection(getDomainClass()); + return template.getCollection(getDomainClass()); } @@ -140,7 +145,7 @@ public class SimpleMongoRepository extends */ public Long count() { - return operations.getCollection(operations.getDefaultCollectionName()) + return template.getCollection(template.getDefaultCollectionName()) .count(); } @@ -156,7 +161,7 @@ public class SimpleMongoRepository 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 extends */ public void deleteAll() { - operations.dropCollection(operations.getDefaultCollectionName()); + template.dropCollection(template.getDefaultCollectionName()); } @@ -197,7 +202,7 @@ public class SimpleMongoRepository extends Long count = count(); List list = - operations.query(new BasicDBObject(), getDomainClass(), + template.query(new BasicDBObject(), getDomainClass(), withPagination(pageable)); return new PageImpl(list, pageable, count); @@ -213,7 +218,7 @@ public class SimpleMongoRepository extends */ public List findAll(final Sort sort) { - return operations.query(new BasicDBObject(), getDomainClass(), + return template.query(new BasicDBObject(), getDomainClass(), withSorting(sort)); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/config/MongoRepositoryConfigDefinitionParser.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/config/MongoRepositoryConfigDefinitionParser.java index 4429376e3..38611907e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/config/MongoRepositoryConfigDefinitionParser.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/config/MongoRepositoryConfigDefinitionParser.java @@ -46,6 +46,6 @@ public class MongoRepositoryConfigDefinitionParser MongoRepositoryConfiguration context, BeanDefinitionBuilder builder, Object beanSource) { - builder.addPropertyReference("operations", context.getMongoTemplateRef()); + builder.addPropertyReference("template", context.getMongoTemplateRef()); } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/MongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/MongoTemplateTests.java index 3990f9376..426e81094 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/MongoTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/MongoTemplateTests.java @@ -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; 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 { 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 result = template.query(QueryBuilder.start("_id").is(converter.convertObjectId(person.getId())).get(), Person.class); + assertThat(result.size(), is(1)); + assertThat(result, hasItem(person)); } } 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 c1021e301..55c629123 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 @@ -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 { 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)); + } + + @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)); + 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/Address.java b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/Address.java new file mode 100644 index 000000000..f8a2ac67f --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/Address.java @@ -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; + } +} 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 6fc1bb714..e781adf5a 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 @@ -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; * * @author Oliver Gierke */ +@RunWith(MockitoJUnitRunner.class) public class MongoQueryCreatorUnitTests { Method findByFirstname; Method findByFirstnameAndFriend; + + @Mock + MongoConverter converter; @Before @@ -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 { new MongoQueryCreator(new PartTree("findByFirstnameAndFriend", Person.class), new SimpleParameterAccessor( new Parameters(findByFirstnameAndFriend), new Object[] { - "Oliver", new Person() })); + "Oliver", new Person() }), converter); creator.createQuery(); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/MongoRepositoryFactoryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/MongoRepositoryFactoryUnitTests.java index 04aa68696..bc7256ab0 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/MongoRepositoryFactoryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/MongoRepositoryFactoryUnitTests.java @@ -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 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); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/Person.java b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/Person.java index 4e863d38d..0f9b73153 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/Person.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/Person.java @@ -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 @@ */ package org.springframework.data.document.mongodb.repository; +import java.util.Set; + import org.bson.types.ObjectId; @@ -29,9 +31,12 @@ public class Person { private String firstname; private String lastname; private Integer age; + + private Address address; + private Set
shippingAddresses; - public Person() { + public Person() { this(null, null); } @@ -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
getShippingAddresses() { + return shippingAddresses; + } + + + /** + * @param addresses the addresses to set + */ + public void setShippingAddresses(Set
addresses) { + this.shippingAddresses = addresses; + } /* 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 aa8c1e371..0fdadc546 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 @@ -66,4 +66,22 @@ public interface PersonRepository extends MongoRepository { * @return */ List 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 findByAddress(Address address); } diff --git a/spring-data-mongodb/src/test/resources/org/springframework/data/document/mongodb/repository/PersonRepositoryIntegrationTests-context.xml b/spring-data-mongodb/src/test/resources/org/springframework/data/document/mongodb/repository/PersonRepositoryIntegrationTests-context.xml index 6ed419707..12550d0de 100644 --- a/spring-data-mongodb/src/test/resources/org/springframework/data/document/mongodb/repository/PersonRepositoryIntegrationTests-context.xml +++ b/spring-data-mongodb/src/test/resources/org/springframework/data/document/mongodb/repository/PersonRepositoryIntegrationTests-context.xml @@ -6,7 +6,7 @@ - +