diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/config/MongoRepositoryConfigParser.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/config/MongoRepositoryConfigParser.java index 7e90d8aaa..80d123630 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/config/MongoRepositoryConfigParser.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/config/MongoRepositoryConfigParser.java @@ -49,5 +49,6 @@ public class MongoRepositoryConfigParser extends BeanDefinitionRegistry registry, Object beanSource) { builder.addPropertyReference("template", context.getMongoTemplateRef()); + builder.addPropertyValue("createIndexesForQueryMethods", context.getCreateQueryIndexes()); } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/config/SimpleMongoRepositoryConfiguration.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/config/SimpleMongoRepositoryConfiguration.java index 9958f4de2..42be4dec1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/config/SimpleMongoRepositoryConfiguration.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/config/SimpleMongoRepositoryConfiguration.java @@ -34,6 +34,7 @@ public class SimpleMongoRepositoryConfiguration RepositoryConfig { private static final String MONGO_TEMPLATE_REF = "mongo-template-ref"; + private static final String CREATE_QUERY_INDEXES = "create-query-indexes"; private static final String DEFAULT_MONGO_TEMPLATE_REF = "mongoTemplate"; /** @@ -57,6 +58,17 @@ public class SimpleMongoRepositoryConfiguration return StringUtils.hasText(templateRef) ? templateRef : DEFAULT_MONGO_TEMPLATE_REF; } + /** + * Returns whether to create indexes for query methods. + * + * @return + */ + public boolean getCreateQueryIndexes() { + + String createQueryIndexes = getSource().getAttribute(CREATE_QUERY_INDEXES); + return StringUtils.hasText(createQueryIndexes) ? Boolean.parseBoolean(createQueryIndexes) : false; + } + /* * (non-Javadoc) * @@ -98,6 +110,8 @@ public class SimpleMongoRepositoryConfiguration SingleRepositoryConfigInformation { String getMongoTemplateRef(); + + boolean getCreateQueryIndexes(); } /** @@ -130,6 +144,15 @@ public class SimpleMongoRepositoryConfiguration return getAttribute(MONGO_TEMPLATE_REF); } + + /* (non-Javadoc) + * @see org.springframework.data.document.mongodb.config.SimpleMongoRepositoryConfiguration.MongoRepositoryConfiguration#getCreateQueryIndexes() + */ + public boolean getCreateQueryIndexes() { + + String attribute = getAttribute(CREATE_QUERY_INDEXES); + return attribute == null ? false : Boolean.parseBoolean(attribute); + } } /** @@ -162,5 +185,12 @@ public class SimpleMongoRepositoryConfiguration return getParent().getMongoTemplateRef(); } + + /* (non-Javadoc) + * @see org.springframework.data.document.mongodb.config.SimpleMongoRepositoryConfiguration.MongoRepositoryConfiguration#getCreateQueryIndexes() + */ + public boolean getCreateQueryIndexes() { + return getParent().getCreateQueryIndexes(); + } } } 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 cb0d287f1..7e19ea8d4 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 @@ -59,6 +59,7 @@ public class MongoRepositoryFactoryBean, S, ID exten RepositoryFactoryBeanSupport { private MongoTemplate template; + private boolean createIndexesForQueryMethods = false; /** * Configures the {@link MongoTemplate} to be used. @@ -70,6 +71,15 @@ public class MongoRepositoryFactoryBean, S, ID exten this.template = template; } + + /** + * Configures whether to automatically create indexes for the properties referenced in a query method. + * + * @param createIndexesForQueryMethods the createIndexesForQueryMethods to set + */ + public void setCreateIndexesForQueryMethods(boolean createIndexesForQueryMethods) { + this.createIndexesForQueryMethods = createIndexesForQueryMethods; + } /* * (non-Javadoc) @@ -82,7 +92,11 @@ public class MongoRepositoryFactoryBean, S, ID exten protected final RepositoryFactorySupport createRepositoryFactory() { RepositoryFactorySupport factory = getFactoryInstance(template); - factory.addQueryCreationListener(new IndexEnsuringQueryCreationListener(template)); + + if (createIndexesForQueryMethods) { + factory.addQueryCreationListener(new IndexEnsuringQueryCreationListener(template)); + } + return factory; } @@ -276,7 +290,7 @@ public class MongoRepositoryFactoryBean, S, ID exten * * @author Oliver Gierke */ - private static class IndexEnsuringQueryCreationListener implements QueryCreationListener { + static class IndexEnsuringQueryCreationListener implements QueryCreationListener { private static final Set GEOSPATIAL_TYPES = new HashSet(Arrays.asList(Type.NEAR, Type.WITHIN)); private static final Log LOG = LogFactory.getLog(IndexEnsuringQueryCreationListener.class); diff --git a/spring-data-mongodb/src/main/resources/org/springframework/data/document/mongodb/config/spring-mongo-1.0.xsd b/spring-data-mongodb/src/main/resources/org/springframework/data/document/mongodb/config/spring-mongo-1.0.xsd index e5d92d50e..b9cdabe5a 100644 --- a/spring-data-mongodb/src/main/resources/org/springframework/data/document/mongodb/config/spring-mongo-1.0.xsd +++ b/spring-data-mongodb/src/main/resources/org/springframework/data/document/mongodb/config/spring-mongo-1.0.xsd @@ -118,6 +118,14 @@ The password to use when connecting to a MongoDB server. + + + + Enables creation of indexes for queries that get derived from the method name + and thus reference domain class properties. Defaults to false. + + + diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/MongoRepositoryFactoryBeanUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/MongoRepositoryFactoryBeanUnitTests.java new file mode 100644 index 000000000..ec754885e --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/MongoRepositoryFactoryBeanUnitTests.java @@ -0,0 +1,86 @@ +/* + * Copyright 2011 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.document.mongodb.repository; + +import static org.mockito.Mockito.*; +import static org.junit.Assert.*; +import static org.hamcrest.CoreMatchers.*; + +import java.util.List; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.springframework.data.document.mongodb.MongoTemplate; +import org.springframework.data.document.mongodb.convert.MongoConverter; +import org.springframework.data.document.mongodb.repository.MongoRepositoryFactoryBean.IndexEnsuringQueryCreationListener; +import org.springframework.data.mapping.context.MappingContext; +import org.springframework.data.repository.core.support.QueryCreationListener; +import org.springframework.data.repository.core.support.RepositoryFactorySupport; +import org.springframework.test.util.ReflectionTestUtils; + +/** + * Unit tests for {@link MongoRepositoryFactoryBean}. + * + * @author Oliver Gierke + */ +@RunWith(MockitoJUnitRunner.class) +public class MongoRepositoryFactoryBeanUnitTests { + + @Mock + MongoTemplate template; + + @Mock + MongoConverter converter; + + @Mock + @SuppressWarnings("rawtypes") + MappingContext context; + + @Test + @SuppressWarnings("rawtypes") + public void addsIndexEnsuringQueryCreationListenerIfConfigured() { + + MongoRepositoryFactoryBean factory = new MongoRepositoryFactoryBean(); + factory.setCreateIndexesForQueryMethods(true); + + List> listeners = getListenersFromFactory(factory); + assertThat(listeners.size(), is(1)); + assertThat(listeners.get(0), is(instanceOf(IndexEnsuringQueryCreationListener.class))); + } + + @Test + @SuppressWarnings("rawtypes") + public void doesNotAddIndexEnsuringQueryCreationListenerByDefault() { + + List> listeners = getListenersFromFactory(new MongoRepositoryFactoryBean()); + assertThat(listeners.isEmpty(), is(true)); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + private List> getListenersFromFactory(MongoRepositoryFactoryBean factoryBean) { + + when(template.getConverter()).thenReturn(converter); + when(converter.getMappingContext()).thenReturn(context); + + factoryBean.setTemplate(template); + factoryBean.afterPropertiesSet(); + + RepositoryFactorySupport factory = factoryBean.createRepositoryFactory(); + return (List>) ReflectionTestUtils.getField(factory, "queryPostProcessors"); + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/RepositoryIndexCreationIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/RepositoryIndexCreationIntegrationTests.java new file mode 100644 index 000000000..126b616c8 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/repository/RepositoryIndexCreationIntegrationTests.java @@ -0,0 +1,78 @@ +/* + * Copyright 2011 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.document.mongodb.repository; + +import static org.junit.Assert.*; +import static org.hamcrest.Matchers.*; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.data.document.mongodb.CollectionCallback; +import org.springframework.data.document.mongodb.MongoOperations; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.mongodb.DBCollection; +import com.mongodb.DBObject; +import com.mongodb.MongoException; + +/** + * Integration test for index creation for query methods. + * + * @author Oliver Gierke + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration +public class RepositoryIndexCreationIntegrationTests { + + @Autowired + MongoOperations operations; + + @After + public void tearDown() { + operations.dropCollection(Person.class); + } + + @Test + public void testname() { + operations.execute(Person.class, new CollectionCallback() { + + public Void doInCollection(DBCollection collection) throws MongoException, DataAccessException { + List indexInfo = collection.getIndexInfo(); + + assertThat(indexInfo.isEmpty(), is(false)); + assertThat(indexInfo.size(), is(greaterThan(2))); + assertThat(getIndexNamesFrom(indexInfo), hasItems("findByLastname", "findByFirstnameNotIn")); + + return null; + } + }); + } + + private static List getIndexNamesFrom(List indexes) { + List result = new ArrayList(); + for (DBObject dbObject : indexes) { + result.add(dbObject.get("name").toString()); + } + return result; + } +} diff --git a/spring-data-mongodb/src/test/resources/org/springframework/data/document/mongodb/repository/RepositoryIndexCreationIntegrationTests-context.xml b/spring-data-mongodb/src/test/resources/org/springframework/data/document/mongodb/repository/RepositoryIndexCreationIntegrationTests-context.xml new file mode 100644 index 000000000..422814e23 --- /dev/null +++ b/spring-data-mongodb/src/test/resources/org/springframework/data/document/mongodb/repository/RepositoryIndexCreationIntegrationTests-context.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + +