Skip to content

Commit aa63e4c

Browse files
committed
DATAMONGO-2188 - Introduce configuration to disable auto-index creation.
Auto-index creation can now be disabled by setting MongoMappingContext.setAutoIndexCreation(false). This configuration prevents automatic index creation on application startup and during access to entities. Auto-index creation comes with automated collection creation. Users that rely on collection creation (e.g. if you wish to use ClientSessions or transactions) must make sure the collection exists prior to session usage.
1 parent 76e7d29 commit aa63e4c

File tree

6 files changed

+94
-29
lines changed

6 files changed

+94
-29
lines changed

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

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -246,10 +246,14 @@ public MongoTemplate(MongoDbFactory mongoDbFactory, @Nullable MongoConverter mon
246246
mappingContext = this.mongoConverter.getMappingContext();
247247
// We create indexes based on mapping events
248248
if (mappingContext instanceof MongoMappingContext) {
249-
indexCreator = new MongoPersistentEntityIndexCreator((MongoMappingContext) mappingContext, this);
250-
eventPublisher = new MongoMappingEventPublisher(indexCreator);
251-
if (mappingContext instanceof ApplicationEventPublisherAware) {
252-
((ApplicationEventPublisherAware) mappingContext).setApplicationEventPublisher(eventPublisher);
249+
250+
MongoMappingContext mappingContext = (MongoMappingContext) this.mappingContext;
251+
252+
if (mappingContext.isAutoIndexCreation()) {
253+
254+
indexCreator = new MongoPersistentEntityIndexCreator(mappingContext, this);
255+
eventPublisher = new MongoMappingEventPublisher(indexCreator);
256+
mappingContext.setApplicationEventPublisher(eventPublisher);
253257
}
254258
}
255259
}
@@ -1582,7 +1586,8 @@ public UpdateResult doInCollection(MongoCollection<Document> collection)
15821586
query.getCollation().map(Collation::toMongoCollation).ifPresent(opts::collation);
15831587
}
15841588

1585-
Document updateObj = update instanceof MappedUpdate ? update.getUpdateObject() : updateMapper.getMappedObject(update.getUpdateObject(), entity);
1589+
Document updateObj = update instanceof MappedUpdate ? update.getUpdateObject()
1590+
: updateMapper.getMappedObject(update.getUpdateObject(), entity);
15861591

15871592
if (multi && update.isIsolated() && !queryObj.containsKey("$isolated")) {
15881593
queryObj.put("$isolated", 1);
@@ -1617,7 +1622,8 @@ public UpdateResult doInCollection(MongoCollection<Document> collection)
16171622
});
16181623
}
16191624

1620-
private void increaseVersionForUpdateIfNecessary(@Nullable MongoPersistentEntity<?> persistentEntity, UpdateDefinition update) {
1625+
private void increaseVersionForUpdateIfNecessary(@Nullable MongoPersistentEntity<?> persistentEntity,
1626+
UpdateDefinition update) {
16211627

16221628
if (persistentEntity != null && persistentEntity.hasVersionProperty()) {
16231629
String versionFieldName = persistentEntity.getRequiredVersionProperty().getFieldName();

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -232,12 +232,15 @@ public ReactiveMongoTemplate(ReactiveMongoDatabaseFactory mongoDatabaseFactory,
232232
if (this.mappingContext instanceof MongoMappingContext) {
233233

234234
MongoMappingContext mongoMappingContext = (MongoMappingContext) this.mappingContext;
235-
this.indexCreator = new ReactiveMongoPersistentEntityIndexCreator(mongoMappingContext, this::indexOps);
236-
this.eventPublisher = new MongoMappingEventPublisher(this.indexCreatorListener);
237235

238-
mongoMappingContext.setApplicationEventPublisher(this.eventPublisher);
239-
this.mappingContext.getPersistentEntities()
240-
.forEach(entity -> onCheckForIndexes(entity, subscriptionExceptionHandler));
236+
if (mongoMappingContext.isAutoIndexCreation()) {
237+
this.indexCreator = new ReactiveMongoPersistentEntityIndexCreator(mongoMappingContext, this::indexOps);
238+
this.eventPublisher = new MongoMappingEventPublisher(this.indexCreatorListener);
239+
240+
mongoMappingContext.setApplicationEventPublisher(this.eventPublisher);
241+
this.mappingContext.getPersistentEntities()
242+
.forEach(entity -> onCheckForIndexes(entity, subscriptionExceptionHandler));
243+
}
241244
}
242245
}
243246

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoMappingContext.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ public class MongoMappingContext extends AbstractMappingContext<BasicMongoPersis
4343

4444
private FieldNamingStrategy fieldNamingStrategy = DEFAULT_NAMING_STRATEGY;
4545
private @Nullable ApplicationContext context;
46+
private boolean autoIndexCreation = true;
4647

4748
/**
4849
* Creates a new {@link MongoMappingContext}.
@@ -101,4 +102,28 @@ public void setApplicationContext(ApplicationContext applicationContext) throws
101102

102103
this.context = applicationContext;
103104
}
105+
106+
/**
107+
* Returns whether auto-index creation is enabled or disabled. Please note that auto-index creation is deprecated.
108+
* Index creation should happen at a well-defined time that is ideally controlled by the application itself.
109+
*
110+
* @return {@literal true} when auto-index creation is enabled; {@literal false} otherwise.
111+
* @since 2.2
112+
* @see org.springframework.data.mongodb.core.index.Indexed
113+
*/
114+
public boolean isAutoIndexCreation() {
115+
return autoIndexCreation;
116+
}
117+
118+
/**
119+
* Enables/disables auto-index creation. Please note that auto-index creation is deprecated. Index creation should
120+
* happen at a well-defined time that is ideally controlled by the application its
121+
*
122+
* @param autoCreateIndexes {@literal true} to enable auto-index creation. Enabled by default.
123+
* @since 2.2
124+
* @see org.springframework.data.mongodb.core.index.Indexed
125+
*/
126+
public void setAutoIndexCreation(boolean autoCreateIndexes) {
127+
this.autoIndexCreation = autoCreateIndexes;
128+
}
104129
}

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public class MongoRepositoryFactoryBean<T extends Repository<S, ID>, S, ID exten
3535
extends RepositoryFactoryBeanSupport<T, S, ID> {
3636

3737
private @Nullable MongoOperations operations;
38-
private boolean createIndexesForQueryMethods = false;
38+
@Deprecated private boolean createIndexesForQueryMethods = false;
3939
private boolean mappingContextConfigured = false;
4040

4141
/**
@@ -60,7 +60,10 @@ public void setMongoOperations(MongoOperations operations) {
6060
* Configures whether to automatically create indexes for the properties referenced in a query method.
6161
*
6262
* @param createIndexesForQueryMethods the createIndexesForQueryMethods to set
63+
* @deprecated since 2.2. Use {@link org.springframework.data.mongodb.core.index.IndexOperations} to define and create
64+
* indexes.
6365
*/
66+
@Deprecated
6467
public void setCreateIndexesForQueryMethods(boolean createIndexesForQueryMethods) {
6568
this.createIndexesForQueryMethods = createIndexesForQueryMethods;
6669
}

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactoryBean.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ public class ReactiveMongoRepositoryFactoryBean<T extends Repository<S, ID>, S,
4040
extends RepositoryFactoryBeanSupport<T, S, ID> {
4141

4242
private @Nullable ReactiveMongoOperations operations;
43-
private boolean createIndexesForQueryMethods = false;
43+
44+
@Deprecated private boolean createIndexesForQueryMethods = false;
4445
private boolean mappingContextConfigured = false;
4546

4647
/**
@@ -65,7 +66,10 @@ public void setReactiveMongoOperations(@Nullable ReactiveMongoOperations operati
6566
* Configures whether to automatically create indexes for the properties referenced in a query method.
6667
*
6768
* @param createIndexesForQueryMethods the createIndexesForQueryMethods to set
69+
* @deprecated since 2.2. Use {@link org.springframework.data.mongodb.core.index.IndexOperations} to define and create
70+
* indexes.
6871
*/
72+
@Deprecated
6973
public void setCreateIndexesForQueryMethods(boolean createIndexesForQueryMethods) {
7074
this.createIndexesForQueryMethods = createIndexesForQueryMethods;
7175
}

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -30,25 +30,26 @@
3030
import org.junit.runner.RunWith;
3131
import org.springframework.beans.factory.annotation.Autowired;
3232
import org.springframework.context.ConfigurableApplicationContext;
33-
import org.springframework.dao.DataAccessException;
33+
import org.springframework.data.mongodb.MongoCollectionUtils;
3434
import org.springframework.data.mongodb.MongoDbFactory;
35-
import org.springframework.data.mongodb.core.CollectionCallback;
3635
import org.springframework.data.mongodb.core.MongoOperations;
36+
import org.springframework.data.mongodb.core.MongoTemplate;
37+
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
38+
import org.springframework.data.mongodb.core.convert.NoOpDbRefResolver;
3739
import org.springframework.data.mongodb.core.mapping.Document;
3840
import org.springframework.data.mongodb.core.mapping.Field;
41+
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
3942
import org.springframework.test.annotation.DirtiesContext;
4043
import org.springframework.test.context.ContextConfiguration;
4144
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
4245

43-
import com.mongodb.MongoException;
44-
import com.mongodb.client.MongoCollection;
45-
4646
/**
4747
* Integration tests for index handling.
4848
*
4949
* @author Oliver Gierke
5050
* @author Christoph Strobl
5151
* @author Jordi Llach
52+
* @author Mark Paluch
5253
*/
5354
@RunWith(SpringJUnit4ClassRunner.class)
5455
@ContextConfiguration("classpath:infrastructure.xml")
@@ -72,6 +73,21 @@ public void createsIndexWithFieldName() {
7273
assertThat(hasIndex("_firstname", IndexedPerson.class), is(true));
7374
}
7475

76+
@Test // DATAMONGO-237
77+
@DirtiesContext
78+
public void shouldNotCreateIndexOnIndexingDisabled() {
79+
80+
MongoMappingContext context = new MongoMappingContext();
81+
context.setAutoIndexCreation(false);
82+
83+
MongoTemplate template = new MongoTemplate(mongoDbFactory,
84+
new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, context));
85+
86+
template.getConverter().getMappingContext().getPersistentEntity(IndexedPerson.class);
87+
88+
assertThat(hasIndex("_firstname", MongoCollectionUtils.getPreferredCollectionName(IndexedPerson.class)), is(false));
89+
}
90+
7591
@Test // DATAMONGO-1163
7692
@DirtiesContext
7793
public void createsIndexFromMetaAnnotation() {
@@ -101,22 +117,30 @@ class IndexedPerson {
101117
* @param entityType
102118
* @return
103119
*/
104-
private boolean hasIndex(final String indexName, Class<?> entityType) {
120+
private boolean hasIndex(String indexName, Class<?> entityType) {
121+
return hasIndex(indexName, operations.getCollectionName(entityType));
122+
}
123+
124+
/**
125+
* Returns whether an index with the given name exists for the given collection.
126+
*
127+
* @param indexName
128+
* @param collectionName
129+
* @return
130+
*/
131+
private boolean hasIndex(String indexName, String collectionName) {
105132

106-
return operations.execute(entityType, new CollectionCallback<Boolean>() {
107-
public Boolean doInCollection(MongoCollection<org.bson.Document> collection)
108-
throws MongoException, DataAccessException {
133+
return operations.execute(collectionName, collection -> {
109134

110-
List<org.bson.Document> indexes = new ArrayList<org.bson.Document>();
111-
collection.listIndexes(org.bson.Document.class).into(indexes);
135+
List<org.bson.Document> indexes = new ArrayList<>();
136+
collection.listIndexes(org.bson.Document.class).into(indexes);
112137

113-
for (org.bson.Document indexInfo : indexes) {
114-
if (indexName.equals(indexInfo.get("name"))) {
115-
return true;
116-
}
138+
for (org.bson.Document indexInfo : indexes) {
139+
if (indexName.equals(indexInfo.get("name"))) {
140+
return true;
117141
}
118-
return false;
119142
}
143+
return false;
120144
});
121145
}
122146
}

0 commit comments

Comments
 (0)