From 4a80c2c7dc444f8e61e5e6772cdb77bdeb03b46a Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Fri, 3 Dec 2010 01:53:30 +0100 Subject: [PATCH] DATADOC-17 - Added initial draft of repository implementation for MongoDB. Currently only supports executing finders for collections and single entities (i.e. no pagination support currently). --- spring-data-mongodb/pom.xml | 18 ++ .../mongodb/MongoExceptionTranslator.java | 39 ++++ .../repository/MongoEntityInformation.java | 100 +++++++++ .../mongodb/repository/MongoQuery.java | 86 ++++++++ .../mongodb/repository/MongoQueryCreator.java | 142 +++++++++++++ .../mongodb/repository/MongoRepository.java | 31 +++ .../MongoRepositoryFactoryBean.java | 126 ++++++++++++ .../repository/SimpleMongoRepository.java | 194 ++++++++++++++++++ .../MongoEntityInformationUnitTests.java | 59 ++++++ .../MongoQueryCreatorUnitTests.java | 79 +++++++ .../document/mongodb/repository/Person.java | 125 +++++++++++ .../mongodb/repository/PersonRepository.java | 29 +++ .../PersonRepositoryIntegrationTests.java | 57 +++++ ...rsonRepositoryIntegrationTests-context.xml | 13 ++ .../mongodb/repository/infrastructure.xml | 19 ++ spring-data-mongodb/template.mf | 2 + 16 files changed, 1119 insertions(+) create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/MongoExceptionTranslator.java create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoEntityInformation.java create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoQuery.java create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoQueryCreator.java create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoRepository.java create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoRepositoryFactoryBean.java create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/SimpleMongoRepository.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/MongoEntityInformationUnitTests.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/MongoQueryCreatorUnitTests.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/Person.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/PersonRepository.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/PersonRepositoryIntegrationTests.java create mode 100644 spring-data-mongodb/src/test/resources/org/springframework/data/document/mongodb/repository/PersonRepositoryIntegrationTests-context.xml create mode 100644 spring-data-mongodb/src/test/resources/org/springframework/data/document/mongodb/repository/infrastructure.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index 78f88b85f..c958525a3 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -21,12 +21,22 @@ org.springframework spring-tx + + org.springframework + spring-test + test + org.springframework.data spring-data-document-core + + org.springframework.data + spring-data-commons-core + ${project.version} + @@ -78,12 +88,20 @@ mockito-all test + + + org.hamcrest + hamcrest-all + 1.1 + test + junit junit + org.mongodb diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/MongoExceptionTranslator.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/MongoExceptionTranslator.java new file mode 100644 index 000000000..013876701 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/MongoExceptionTranslator.java @@ -0,0 +1,39 @@ +/* + * Copyright 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; + +import org.springframework.dao.DataAccessException; +import org.springframework.dao.support.PersistenceExceptionTranslator; + + +/** + * Simple {@link PersistenceExceptionTranslator} for Mongo. + * + * @author Oliver Gierke + */ +public class MongoExceptionTranslator implements PersistenceExceptionTranslator { + + /* + * (non-Javadoc) + * + * @see org.springframework.dao.support.PersistenceExceptionTranslator# + * translateExceptionIfPossible(java.lang.RuntimeException) + */ + public DataAccessException translateExceptionIfPossible(RuntimeException ex) { + + return MongoDbUtils.translateMongoExceptionIfPossible(ex); + } +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoEntityInformation.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoEntityInformation.java new file mode 100644 index 000000000..1d62c6d50 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoEntityInformation.java @@ -0,0 +1,100 @@ +/* + * Copyright 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 java.lang.reflect.Field; +import java.util.Arrays; +import java.util.List; + +import org.springframework.data.repository.support.IdAware; +import org.springframework.data.repository.support.IsNewAware; +import org.springframework.util.ReflectionUtils; + + +/** + * Expects the domain class to contain a field with a name out of the following + * {@value #FIELD_NAMES}. + * + * @author Oliver Gierke + */ +class MongoEntityInformation implements IsNewAware, IdAware { + + private final List FIELD_NAMES = Arrays.asList("ID", "id", "_id"); + private Field field; + + + /** + * Creates a new {@link MongoEntityInformation}. + * + * @param domainClass + */ + public MongoEntityInformation(Class domainClass) { + + for (String name : FIELD_NAMES) { + + Field field = ReflectionUtils.findField(domainClass, name); + + if (field != null) { + ReflectionUtils.makeAccessible(field); + this.field = field; + break; + } + } + + if (this.field == null) { + throw new IllegalArgumentException(String.format( + "Given domain class %s does not contain an id property!", + domainClass.getName())); + } + } + + + /* + * (non-Javadoc) + * + * @see + * org.springframework.data.repository.support.IsNewAware#isNew(java.lang + * .Object) + */ + public boolean isNew(Object entity) { + + return null == ReflectionUtils.getField(field, entity); + } + + + /** + * Returns the actual field name containing the id. + * + * @return + */ + public String getFieldName() { + + return field.getName(); + } + + + /* + * (non-Javadoc) + * + * @see + * org.springframework.data.repository.support.IdAware#getId(java.lang.Object + * ) + */ + public Object getId(Object entity) { + + return ReflectionUtils.getField(field, entity); + } +} \ No newline at end of file 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 new file mode 100644 index 000000000..c06ba3b3d --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoQuery.java @@ -0,0 +1,86 @@ +/* + * 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 java.util.List; + +import org.springframework.data.document.mongodb.MongoTemplate; +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.DBObject; + + +/** + * {@link RepositoryQuery} implementation for Mongo. + * + * @author Oliver Gierke + */ +public class MongoQuery 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 + * {@link MongoTemplate}. + * + * @param method + * @param template + */ + public MongoQuery(QueryMethod method, MongoTemplate template) { + + Assert.notNull(template); + Assert.notNull(method); + Assert.isTrue(!method.isPageQuery(), + "Pagination queries not supported!"); + + this.method = method; + this.template = template; + this.tree = new PartTree(method.getName(), method.getDomainClass()); + } + + + /* + * (non-Javadoc) + * + * @see + * org.springframework.data.repository.query.RepositoryQuery#execute(java + * .lang.Object[]) + */ + public Object execute(Object[] parameters) { + + SimpleParameterAccessor accessor = + new SimpleParameterAccessor(method.getParameters(), parameters); + MongoQueryCreator creator = new MongoQueryCreator(tree, accessor); + DBObject query = creator.createQuery(); + + List result = + template.query(template.getDefaultCollectionName(), query, + method.getDomainClass()); + + if (method.isCollectionQuery()) { + return result; + } else { + return result.isEmpty() ? null : result.get(0); + } + } +} 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 new file mode 100644 index 000000000..1b97ee0d9 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoQueryCreator.java @@ -0,0 +1,142 @@ +/* + * 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.domain.Sort; +import org.springframework.data.repository.query.SimpleParameterAccessor; +import org.springframework.data.repository.query.SimpleParameterAccessor.BindableParameterIterator; +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.DBObject; +import com.mongodb.QueryBuilder; + + +/** + * Custom query creator to create Mongo criterias. + * + * @author Oliver Gierke + */ +class MongoQueryCreator extends AbstractQueryCreator { + + /** + * Creates a new {@link MongoQueryCreator} from the given {@link PartTree} + * and {@link SimpleParameterAccessor}. + * + * @param tree + * @param accessor + */ + public MongoQueryCreator(PartTree tree, SimpleParameterAccessor accessor) { + + super(tree, accessor); + } + + + /* + * (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) + */ + @Override + protected QueryBuilder create(Part part, BindableParameterIterator iterator) { + + return from(part.getType(), QueryBuilder.start(part.getProperty()), + iterator); + } + + + /* + * (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) + */ + @Override + protected QueryBuilder and(Part part, QueryBuilder base, + BindableParameterIterator iterator) { + + return from(part.getType(), base.and(part.getProperty()), iterator); + } + + + /* + * (non-Javadoc) + * + * @see + * org.springframework.data.document.mongodb.repository.AbstractQueryCreator + * #reduceCriterias(java.lang.Object, java.lang.Object) + */ + @Override + protected QueryBuilder or(QueryBuilder base, QueryBuilder criteria) { + + base.or(criteria.get()); + return base; + } + + + /* + * (non-Javadoc) + * + * @see + * org.springframework.data.document.mongodb.repository.AbstractQueryCreator + * #finalize(java.lang.Object) + */ + @Override + protected DBObject finalize(QueryBuilder criteria, Sort sort) { + + // TODO: apply sorting + return criteria.get(); + } + + + /** + * Populates the given {@link Criteria} depending on the {@link Type} given. + * + * @param type + * @param criteria + * @param parameters + * @return + */ + private QueryBuilder from(Type type, QueryBuilder criteria, + BindableParameterIterator parameters) { + + switch (type) { + case GREATER_THAN: + return criteria.greaterThan(parameters.next()); + case LESS_THAN: + return criteria.lessThan(parameters.next()); + case IS_NOT_NULL: + return criteria.notEquals(null); + case IS_NULL: + return criteria.is(null); + case SIMPLE_PROPERTY: + return criteria.is(parameters.next()); + case NEGATING_SIMPLE_PROPERTY: + return criteria.notEquals(parameters.next()); + } + + throw new IllegalArgumentException("Unsupported keyword!"); + } +} \ No newline at end of file diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoRepository.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoRepository.java new file mode 100644 index 000000000..7d9b53856 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoRepository.java @@ -0,0 +1,31 @@ +/* + * 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 java.io.Serializable; + +import org.springframework.data.repository.Repository; + + +/** + * Mongo specific {@link Repository} interface. + * + * @author Oliver Gierke + */ +public interface MongoRepository extends + Repository { + +} 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 new file mode 100644 index 000000000..71bc673f4 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/MongoRepositoryFactoryBean.java @@ -0,0 +1,126 @@ +/* + * 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 java.io.Serializable; +import java.lang.reflect.Method; + +import org.springframework.beans.factory.FactoryBean; +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; +import org.springframework.data.repository.support.RepositorySupport; +import org.springframework.util.Assert; + + +/** + * {@link FactoryBean} to create {@link MongoRepository} instances. + * + * @author Oliver Gierke + */ +public class MongoRepositoryFactoryBean extends + RepositoryFactoryBeanSupport> { + + private MongoTemplate template; + + + /** + * Configures the {@link MongoTemplate} to be used. + * + * @param template the template to set + */ + public void setTemplate(MongoTemplate template) { + + this.template = template; + } + + + /* + * (non-Javadoc) + * + * @see + * org.springframework.data.repository.support.RepositoryFactoryBeanSupport + * #createRepositoryFactory() + */ + @Override + protected RepositoryFactorySupport createRepositoryFactory() { + + return new MongoRepositoryFactory(); + } + + + /* + * (non-Javadoc) + * + * @see + * org.springframework.data.repository.support.RepositoryFactoryBeanSupport + * #afterPropertiesSet() + */ + @Override + public void afterPropertiesSet() { + + super.afterPropertiesSet(); + Assert.notNull(template, "MongoTemplate must not be null!"); + } + + /** + * Repository to create {@link MongoRepository} instances. + * + * @author Oliver Gierke + */ + private class MongoRepositoryFactory extends RepositoryFactorySupport { + + @Override + protected RepositorySupport getTargetRepository( + Class domainClass) { + + return new SimpleMongoRepository(domainClass, template); + } + + + @Override + @SuppressWarnings("rawtypes") + protected Class getRepositoryClass() { + + return SimpleMongoRepository.class; + } + + + @Override + protected QueryLookupStrategy getQueryLookupStrategy(Key key) { + + return new MongoQueryLookupStrategy(); + } + + /** + * {@link QueryLookupStrategy} to create {@link MongoQuery} instances. + * + * @author Oliver Gierke + */ + private class MongoQueryLookupStrategy implements QueryLookupStrategy { + + public RepositoryQuery resolveQuery(Method method) { + + 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 new file mode 100644 index 000000000..7ba978c3b --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/repository/SimpleMongoRepository.java @@ -0,0 +1,194 @@ +/* + * 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 java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import org.springframework.data.document.mongodb.MongoTemplate; +import org.springframework.data.repository.support.IsNewAware; +import org.springframework.data.repository.support.RepositorySupport; +import org.springframework.util.Assert; + +import com.mongodb.QueryBuilder; + + +/** + * Repository base implementation for Mongo. + * + * @author Oliver Gierke + */ +public class SimpleMongoRepository extends + RepositorySupport { + + private final MongoTemplate template; + private MongoEntityInformation entityInformation; + + + /** + * @param domainClass + * @param template + */ + public SimpleMongoRepository(Class domainClass, MongoTemplate template) { + + super(domainClass); + + Assert.notNull(template); + this.template = template; + } + + + /* + * (non-Javadoc) + * + * @see + * org.springframework.data.repository.Repository#save(java.lang.Object) + */ + public T save(T entity) { + + template.save(entity); + return entity; + } + + + /* + * (non-Javadoc) + * + * @see + * org.springframework.data.repository.Repository#save(java.lang.Iterable) + */ + public List save(Iterable entities) { + + List result = new ArrayList(); + + for (T entity : entities) { + template.save(entity); + result.add(entity); + } + + return result; + } + + + /* + * (non-Javadoc) + * + * @see + * org.springframework.data.repository.Repository#findById(java.io.Serializable + * ) + */ + public T findById(ID id) { + + List result = + template.query(template.getDefaultCollectionName(), + QueryBuilder.start("_id").get(), getDomainClass()); + + return result.isEmpty() ? null : result.get(0); + } + + + /* + * (non-Javadoc) + * + * @see + * org.springframework.data.repository.Repository#exists(java.io.Serializable + * ) + */ + public boolean exists(ID id) { + + return findById(id) == null; + } + + + /* + * (non-Javadoc) + * + * @see org.springframework.data.repository.Repository#findAll() + */ + public List findAll() { + + return template.getCollection(getDomainClass()); + } + + + /* + * (non-Javadoc) + * + * @see org.springframework.data.repository.Repository#count() + */ + public Long count() { + + return Long.valueOf(findAll().size()); + } + + + /* + * (non-Javadoc) + * + * @see + * org.springframework.data.repository.Repository#delete(java.lang.Object) + */ + public void delete(T entity) { + + QueryBuilder builder = + QueryBuilder.start(entityInformation.getFieldName()).is( + entityInformation.getId(entity)); + template.remove(builder.get()); + } + + + /* + * (non-Javadoc) + * + * @see + * org.springframework.data.repository.Repository#delete(java.lang.Iterable) + */ + public void delete(Iterable entities) { + + for (T entity : entities) { + delete(entity); + } + } + + + /* + * (non-Javadoc) + * + * @see org.springframework.data.repository.Repository#deleteAll() + */ + public void deleteAll() { + + template.dropCollection(template.getDefaultCollectionName()); + } + + + /* + * (non-Javadoc) + * + * @see org.springframework.data.repository.support.RepositorySupport# + * createIsNewStrategy(java.lang.Class) + */ + @Override + protected IsNewAware createIsNewStrategy(Class domainClass) { + + if (entityInformation == null) { + this.entityInformation = new MongoEntityInformation(domainClass); + } + + return entityInformation; + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/MongoEntityInformationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/MongoEntityInformationUnitTests.java new file mode 100644 index 000000000..68e935ccb --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/MongoEntityInformationUnitTests.java @@ -0,0 +1,59 @@ +/* + * 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 static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; + +import org.junit.Test; + + +/** + * Unit test for {@link MongoEntityInformation}. + * + * @author Oliver Gierke + */ +public class MongoEntityInformationUnitTests { + + @Test + public void findsIdField() throws Exception { + + MongoEntityInformation isNewAware = + new MongoEntityInformation(Person.class); + + Person person = new Person(); + assertThat(isNewAware.isNew(person), is(true)); + person.id = 1L; + assertThat(isNewAware.isNew(person), is(false)); + } + + + @Test(expected = IllegalArgumentException.class) + public void rejectsClassIfNoIdField() throws Exception { + + new MongoEntityInformation(InvalidPerson.class); + } + + class Person { + + Long id; + } + + class InvalidPerson { + + Long foo; + } +} 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 new file mode 100644 index 000000000..6fc1bb714 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/MongoQueryCreatorUnitTests.java @@ -0,0 +1,79 @@ +/* + * 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 java.lang.reflect.Method; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; +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; + + +/** + * Unit test for {@link MongoQueryCreator}. + * + * @author Oliver Gierke + */ +public class MongoQueryCreatorUnitTests { + + Method findByFirstname; + Method findByFirstnameAndFriend; + + + @Before + public void setUp() throws SecurityException, NoSuchMethodException { + + findByFirstname = + Sample.class.getMethod("findByFirstname", String.class); + findByFirstnameAndFriend = + Sample.class.getMethod("findByFirstnameAndFriend", + String.class, Person.class); + + } + + + @Test + public void createsQueryCorrectly() throws Exception { + + PartTree tree = new PartTree("findByFirstname", Person.class); + + MongoQueryCreator creator = + new MongoQueryCreator(tree, new SimpleParameterAccessor( + new Parameters(findByFirstname), + new Object[] { "Oliver" })); + + creator.createQuery(); + + creator = + new MongoQueryCreator(new PartTree("findByFirstnameAndFriend", + Person.class), new SimpleParameterAccessor( + new Parameters(findByFirstnameAndFriend), new Object[] { + "Oliver", new Person() })); + creator.createQuery(); + } + + interface Sample { + + List findByFirstname(String firstname); + + + List findByFirstnameAndFriend(String firstname, Person friend); + } +} 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 new file mode 100644 index 000000000..95e20a6b7 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/Person.java @@ -0,0 +1,125 @@ +/* + * 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.bson.types.ObjectId; + + +/** + * Sample domain class. + * + * @author Oliver Gierke + */ +public class Person { + + private String id; + private String firstname; + private String lastname; + + + public Person() { + + this.id = ObjectId.get().toString(); + } + + + /** + * @param id the id to set + */ + public void setId(String id) { + + this.id = id; + } + + + /** + * @return the id + */ + public String getId() { + + return id; + } + + + /** + * @return the firstname + */ + public String getFirstname() { + + return firstname; + } + + + /** + * @param firstname the firstname to set + */ + public void setFirstname(String firstname) { + + this.firstname = firstname; + } + + + /** + * @return the lastname + */ + public String getLastname() { + + return lastname; + } + + + /** + * @param lastname the lastname to set + */ + public void setLastname(String lastname) { + + this.lastname = lastname; + } + + + /* + * (non-Javadoc) + * + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + + if (this == obj) { + return true; + } + + if (obj == null || !getClass().equals(obj.getClass())) { + return false; + } + + Person that = (Person) obj; + + return this.id.equals(that.id); + } + + + /* + * (non-Javadoc) + * + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + + return id.hashCode(); + } +} 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 new file mode 100644 index 000000000..2db31fcea --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/PersonRepository.java @@ -0,0 +1,29 @@ +/* + * 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 java.util.List; + + +/** + * Sample repository managing {@link Person} entities. + * + * @author Oliver Gierke + */ +public interface PersonRepository extends MongoRepository { + + List findByLastname(String lastname); +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/PersonRepositoryIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/PersonRepositoryIntegrationTests.java new file mode 100644 index 000000000..8f8c987eb --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/PersonRepositoryIntegrationTests.java @@ -0,0 +1,57 @@ +/* + * 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 static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; + +import java.util.List; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + + +/** + * Integration test for {@link PersonRepository}. + * + * @author Oliver Gierke + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration +public class PersonRepositoryIntegrationTests { + + @Autowired + PersonRepository repository; + + + @Test + public void createAndExecuteFinderRoundtrip() throws Exception { + + repository.deleteAll(); + + Person person = new Person(); + person.setFirstname("Oliver"); + person.setLastname("Gierke"); + person = repository.save(person); + + List result = repository.findByLastname("Gierke"); + assertThat(result.size(), is(1)); + assertThat(result, hasItem(person)); + } +} 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 new file mode 100644 index 000000000..462d3b2e2 --- /dev/null +++ b/spring-data-mongodb/src/test/resources/org/springframework/data/document/mongodb/repository/PersonRepositoryIntegrationTests-context.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/spring-data-mongodb/src/test/resources/org/springframework/data/document/mongodb/repository/infrastructure.xml b/spring-data-mongodb/src/test/resources/org/springframework/data/document/mongodb/repository/infrastructure.xml new file mode 100644 index 000000000..e216cb973 --- /dev/null +++ b/spring-data-mongodb/src/test/resources/org/springframework/data/document/mongodb/repository/infrastructure.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + diff --git a/spring-data-mongodb/template.mf b/spring-data-mongodb/template.mf index 66246669d..f627242f3 100644 --- a/spring-data-mongodb/template.mf +++ b/spring-data-mongodb/template.mf @@ -11,7 +11,9 @@ Import-Template: org.springframework.util.*;version="[3.0.0, 4.0.0)", org.springframework.transaction.*;version="[3.0.0, 4.0.0)", org.springframework.data.core.*;version="[1.0.0, 2.0.0)", + org.springframework.data.domain.*;version="[1.0.0, 2.0.0)", org.springframework.data.document.*;version="[1.0.0, 2.0.0)", + org.springframework.data.repository.*;version="[1.0.0, 2.0.0)", com.mongodb.*;version="0", org.bson.*;version="0", org.aopalliance.*;version="[1.0.0, 2.0.0)";resolution:=optional,