Browse Source

DATAMONGO-1678 - Polishing.

Use Lombok's Value annotation for immutable value objects. Use IllegalArgumentException for NonNull validation exceptions. Introduce missing generics. Use static methods where possible. Remove unused WriteConcernResolver. Trim whitespaces, formatting.

Original pull request: #472.
pull/472/merge
Mark Paluch 9 years ago
parent
commit
34986df70b
  1. 2
      lombok.config
  2. 4
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/BulkOperations.java
  3. 84
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultBulkOperations.java
  4. 1
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java
  5. 29
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java

2
lombok.config

@ -0,0 +1,2 @@
lombok.nonNull.exceptionType = IllegalArgumentException
lombok.log.fieldName = LOG

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

@ -1,5 +1,5 @@
/* /*
* Copyright 2015-2016 the original author or authors. * Copyright 2015-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -139,7 +139,7 @@ public interface BulkOperations {
* Execute all bulk operations using the default write concern. * Execute all bulk operations using the default write concern.
* *
* @return Result of the bulk operation providing counters for inserts/updates etc. * @return Result of the bulk operation providing counters for inserts/updates etc.
* @throws {@link BulkOperationException} if an error occurred during bulk processing. * @throws org.springframework.data.mongodb.BulkOperationException if an error occurred during bulk processing.
*/ */
BulkWriteResult execute(); BulkWriteResult execute();
} }

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

@ -15,10 +15,11 @@
*/ */
package org.springframework.data.mongodb.core; package org.springframework.data.mongodb.core;
import lombok.Data; import lombok.NonNull;
import lombok.Value;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -54,6 +55,7 @@ import com.mongodb.client.model.WriteModel;
* @author Tobias Trelle * @author Tobias Trelle
* @author Oliver Gierke * @author Oliver Gierke
* @author Christoph Strobl * @author Christoph Strobl
* @author Mark Paluch
* @since 1.9 * @since 1.9
*/ */
class DefaultBulkOperations implements BulkOperations { class DefaultBulkOperations implements BulkOperations {
@ -61,15 +63,13 @@ class DefaultBulkOperations implements BulkOperations {
private final MongoOperations mongoOperations; private final MongoOperations mongoOperations;
private final String collectionName; private final String collectionName;
private final BulkOperationContext bulkOperationContext; private final BulkOperationContext bulkOperationContext;
private final List<WriteModel<Document>> models = new ArrayList<>();
private WriteConcernResolver writeConcernResolver;
private PersistenceExceptionTranslator exceptionTranslator; private PersistenceExceptionTranslator exceptionTranslator;
private WriteConcern defaultWriteConcern; private WriteConcern defaultWriteConcern;
private BulkWriteOptions bulkOptions; private BulkWriteOptions bulkOptions;
List<WriteModel<Document>> models = new ArrayList<>();
/** /**
* Creates a new {@link DefaultBulkOperations} for the given {@link MongoOperations}, collection name and * Creates a new {@link DefaultBulkOperations} for the given {@link MongoOperations}, collection name and
* {@link BulkOperationContext}. * {@link BulkOperationContext}.
@ -90,7 +90,7 @@ class DefaultBulkOperations implements BulkOperations {
this.collectionName = collectionName; this.collectionName = collectionName;
this.bulkOperationContext = bulkOperationContext; this.bulkOperationContext = bulkOperationContext;
this.exceptionTranslator = new MongoExceptionTranslator(); this.exceptionTranslator = new MongoExceptionTranslator();
this.bulkOptions = initBulkOperation(); this.bulkOptions = getBulkWriteOptions(bulkOperationContext.getBulkMode());
} }
/** /**
@ -102,22 +102,12 @@ class DefaultBulkOperations implements BulkOperations {
this.exceptionTranslator = exceptionTranslator == null ? new MongoExceptionTranslator() : exceptionTranslator; this.exceptionTranslator = exceptionTranslator == null ? new MongoExceptionTranslator() : exceptionTranslator;
} }
/**
* Configures the {@link WriteConcernResolver} to be used. Defaults to {@link DefaultWriteConcernResolver}.
*
* @param writeConcernResolver can be {@literal null}.
*/
public void setWriteConcernResolver(WriteConcernResolver writeConcernResolver) {
this.writeConcernResolver = writeConcernResolver == null ? DefaultWriteConcernResolver.INSTANCE
: writeConcernResolver;
}
/** /**
* Configures the default {@link WriteConcern} to be used. Defaults to {@literal null}. * Configures the default {@link WriteConcern} to be used. Defaults to {@literal null}.
* *
* @param defaultWriteConcern can be {@literal null}. * @param defaultWriteConcern can be {@literal null}.
*/ */
public void setDefaultWriteConcern(WriteConcern defaultWriteConcern) { void setDefaultWriteConcern(WriteConcern defaultWriteConcern) {
this.defaultWriteConcern = defaultWriteConcern; this.defaultWriteConcern = defaultWriteConcern;
} }
@ -140,6 +130,7 @@ class DefaultBulkOperations implements BulkOperations {
mongoOperations.getConverter().write(document, sink); mongoOperations.getConverter().write(document, sink);
models.add(new InsertOneModel<>(sink)); models.add(new InsertOneModel<>(sink));
return this; return this;
} }
@ -152,9 +143,7 @@ class DefaultBulkOperations implements BulkOperations {
Assert.notNull(documents, "Documents must not be null!"); Assert.notNull(documents, "Documents must not be null!");
for (Object document : documents) { documents.forEach(this::insert);
insert(document);
}
return this; return this;
} }
@ -170,7 +159,7 @@ class DefaultBulkOperations implements BulkOperations {
Assert.notNull(query, "Query must not be null!"); Assert.notNull(query, "Query must not be null!");
Assert.notNull(update, "Update must not be null!"); Assert.notNull(update, "Update must not be null!");
return updateOne(Arrays.asList(Pair.of(query, update))); return updateOne(Collections.singletonList(Pair.of(query, update)));
} }
/* /*
@ -200,7 +189,7 @@ class DefaultBulkOperations implements BulkOperations {
Assert.notNull(query, "Query must not be null!"); Assert.notNull(query, "Query must not be null!");
Assert.notNull(update, "Update must not be null!"); Assert.notNull(update, "Update must not be null!");
return updateMulti(Arrays.asList(Pair.of(query, update))); return updateMulti(Collections.singletonList(Pair.of(query, update)));
} }
/* /*
@ -254,7 +243,8 @@ class DefaultBulkOperations implements BulkOperations {
DeleteOptions deleteOptions = new DeleteOptions(); DeleteOptions deleteOptions = new DeleteOptions();
query.getCollation().map(Collation::toMongoCollation).ifPresent(deleteOptions::collation); query.getCollation().map(Collation::toMongoCollation).ifPresent(deleteOptions::collation);
models.add(new DeleteManyModel(query.getQueryObject(), deleteOptions)); models.add(new DeleteManyModel<>(query.getQueryObject(), deleteOptions));
return this; return this;
} }
@ -296,7 +286,7 @@ class DefaultBulkOperations implements BulkOperations {
throw toThrow == null ? o_O : toThrow; throw toThrow == null ? o_O : toThrow;
} finally { } finally {
this.bulkOptions = initBulkOperation(); this.bulkOptions = getBulkWriteOptions(bulkOperationContext.getBulkMode());
} }
} }
@ -323,20 +313,8 @@ class DefaultBulkOperations implements BulkOperations {
} else { } else {
models.add(new UpdateOneModel<>(query.getQueryObject(), update.getUpdateObject(), options)); models.add(new UpdateOneModel<>(query.getQueryObject(), update.getUpdateObject(), options));
} }
return this;
}
private final BulkWriteOptions initBulkOperation() {
BulkWriteOptions options = new BulkWriteOptions();
switch (bulkOperationContext.getBulkMode()) { return this;
case ORDERED:
return options.ordered(true);
case UNORDERED:
return options.ordered(false);
}
throw new IllegalStateException("BulkMode was null!");
} }
private WriteModel<Document> mapWriteModel(WriteModel<Document> writeModel) { private WriteModel<Document> mapWriteModel(WriteModel<Document> writeModel) {
@ -345,7 +323,7 @@ class DefaultBulkOperations implements BulkOperations {
UpdateOneModel<Document> model = (UpdateOneModel<Document>) writeModel; UpdateOneModel<Document> model = (UpdateOneModel<Document>) writeModel;
return new UpdateOneModel(getMappedQuery(model.getFilter()), getMappedUpdate(model.getUpdate()), return new UpdateOneModel<>(getMappedQuery(model.getFilter()), getMappedUpdate(model.getUpdate()),
model.getOptions()); model.getOptions());
} }
@ -353,7 +331,7 @@ class DefaultBulkOperations implements BulkOperations {
UpdateManyModel<Document> model = (UpdateManyModel<Document>) writeModel; UpdateManyModel<Document> model = (UpdateManyModel<Document>) writeModel;
return new UpdateManyModel(getMappedQuery(model.getFilter()), getMappedUpdate(model.getUpdate()), return new UpdateManyModel<>(getMappedQuery(model.getFilter()), getMappedUpdate(model.getUpdate()),
model.getOptions()); model.getOptions());
} }
@ -361,14 +339,14 @@ class DefaultBulkOperations implements BulkOperations {
DeleteOneModel<Document> model = (DeleteOneModel<Document>) writeModel; DeleteOneModel<Document> model = (DeleteOneModel<Document>) writeModel;
return new DeleteOneModel(getMappedQuery(model.getFilter()), model.getOptions()); return new DeleteOneModel<>(getMappedQuery(model.getFilter()), model.getOptions());
} }
if (writeModel instanceof DeleteManyModel) { if (writeModel instanceof DeleteManyModel) {
DeleteManyModel<Document> model = (DeleteManyModel<Document>) writeModel; DeleteManyModel<Document> model = (DeleteManyModel<Document>) writeModel;
return new DeleteManyModel(getMappedQuery(model.getFilter()), model.getOptions()); return new DeleteManyModel<>(getMappedQuery(model.getFilter()), model.getOptions());
} }
return writeModel; return writeModel;
@ -382,6 +360,20 @@ class DefaultBulkOperations implements BulkOperations {
return bulkOperationContext.getQueryMapper().getMappedObject(query, bulkOperationContext.getEntity()); return bulkOperationContext.getQueryMapper().getMappedObject(query, bulkOperationContext.getEntity());
} }
private static BulkWriteOptions getBulkWriteOptions(BulkMode bulkMode) {
BulkWriteOptions options = new BulkWriteOptions();
switch (bulkMode) {
case ORDERED:
return options.ordered(true);
case UNORDERED:
return options.ordered(false);
}
throw new IllegalStateException("BulkMode was null!");
}
/** /**
* {@link BulkOperationContext} holds information about * {@link BulkOperationContext} holds information about
* {@link org.springframework.data.mongodb.core.BulkOperations.BulkMode} the entity in use as well as references to * {@link org.springframework.data.mongodb.core.BulkOperations.BulkMode} the entity in use as well as references to
@ -390,12 +382,12 @@ class DefaultBulkOperations implements BulkOperations {
* @author Christoph Strobl * @author Christoph Strobl
* @since 2.0 * @since 2.0
*/ */
@Data @Value
static class BulkOperationContext { static class BulkOperationContext {
final BulkMode bulkMode; @NonNull BulkMode bulkMode;
final Optional<? extends MongoPersistentEntity<?>> entity; @NonNull Optional<? extends MongoPersistentEntity<?>> entity;
final QueryMapper queryMapper; @NonNull QueryMapper queryMapper;
final UpdateMapper updateMapper; @NonNull UpdateMapper updateMapper;
} }
} }

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

@ -562,7 +562,6 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
new BulkOperationContext(mode, getPersistentEntity(entityType), queryMapper, updateMapper)); new BulkOperationContext(mode, getPersistentEntity(entityType), queryMapper, updateMapper));
operations.setExceptionTranslator(exceptionTranslator); operations.setExceptionTranslator(exceptionTranslator);
operations.setWriteConcernResolver(writeConcernResolver);
operations.setDefaultWriteConcern(writeConcern); operations.setDefaultWriteConcern(writeConcern);
return operations; return operations;

29
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java

@ -29,6 +29,7 @@ import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor; import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner; import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.data.annotation.Id; import org.springframework.data.annotation.Id;
@ -51,14 +52,18 @@ import com.mongodb.client.model.UpdateOneModel;
import com.mongodb.client.model.WriteModel; import com.mongodb.client.model.WriteModel;
/** /**
* Unit tests for {@link DefaultBulkOperations}.
*
* @author Christoph Strobl * @author Christoph Strobl
* @author Mark Paluch
*/ */
@RunWith(MockitoJUnitRunner.class) @RunWith(MockitoJUnitRunner.class)
public class DefaultBulkOperationsUnitTests { public class DefaultBulkOperationsUnitTests {
@Mock MongoTemplate template; @Mock MongoTemplate template;
@Mock MongoCollection collection; @Mock MongoCollection<Document> collection;
@Mock DbRefResolver dbRefResolver; @Mock DbRefResolver dbRefResolver;
@Captor ArgumentCaptor<List<WriteModel<Document>>> captor;
MongoConverter converter; MongoConverter converter;
MongoMappingContext mappingContext; MongoMappingContext mappingContext;
@ -85,27 +90,23 @@ public class DefaultBulkOperationsUnitTests {
ops.updateOne(new BasicQuery("{}").collation(Collation.of("de")), new Update().set("lastName", "targaryen")) ops.updateOne(new BasicQuery("{}").collation(Collation.of("de")), new Update().set("lastName", "targaryen"))
.execute(); .execute();
ArgumentCaptor<List<WriteModel<Document>>> captor = ArgumentCaptor.forClass(List.class);
verify(collection).bulkWrite(captor.capture(), any()); verify(collection).bulkWrite(captor.capture(), any());
assertThat(captor.getValue().get(0)).isInstanceOf(UpdateOneModel.class); assertThat(captor.getValue().get(0)).isInstanceOf(UpdateOneModel.class);
assertThat(((UpdateOneModel) captor.getValue().get(0)).getOptions().getCollation()) assertThat(((UpdateOneModel<Document>) captor.getValue().get(0)).getOptions().getCollation())
.isEqualTo(com.mongodb.client.model.Collation.builder().locale("de").build()); .isEqualTo(com.mongodb.client.model.Collation.builder().locale("de").build());
} }
@Test // DATAMONGO-1518 @Test // DATAMONGO-1518
public void updateMayShouldUseCollationWhenPresent() { public void updateManyShouldUseCollationWhenPresent() {
ops.updateMulti(new BasicQuery("{}").collation(Collation.of("de")), new Update().set("lastName", "targaryen")) ops.updateMulti(new BasicQuery("{}").collation(Collation.of("de")), new Update().set("lastName", "targaryen"))
.execute(); .execute();
ArgumentCaptor<List<WriteModel<Document>>> captor = ArgumentCaptor.forClass(List.class);
verify(collection).bulkWrite(captor.capture(), any()); verify(collection).bulkWrite(captor.capture(), any());
assertThat(captor.getValue().get(0)).isInstanceOf(UpdateManyModel.class); assertThat(captor.getValue().get(0)).isInstanceOf(UpdateManyModel.class);
assertThat(((UpdateManyModel) captor.getValue().get(0)).getOptions().getCollation()) assertThat(((UpdateManyModel<Document>) captor.getValue().get(0)).getOptions().getCollation())
.isEqualTo(com.mongodb.client.model.Collation.builder().locale("de").build()); .isEqualTo(com.mongodb.client.model.Collation.builder().locale("de").build());
} }
@ -114,12 +115,10 @@ public class DefaultBulkOperationsUnitTests {
ops.remove(new BasicQuery("{}").collation(Collation.of("de"))).execute(); ops.remove(new BasicQuery("{}").collation(Collation.of("de"))).execute();
ArgumentCaptor<List<WriteModel<Document>>> captor = ArgumentCaptor.forClass(List.class);
verify(collection).bulkWrite(captor.capture(), any()); verify(collection).bulkWrite(captor.capture(), any());
assertThat(captor.getValue().get(0)).isInstanceOf(DeleteManyModel.class); assertThat(captor.getValue().get(0)).isInstanceOf(DeleteManyModel.class);
assertThat(((DeleteManyModel) captor.getValue().get(0)).getOptions().getCollation()) assertThat(((DeleteManyModel<Document>) captor.getValue().get(0)).getOptions().getCollation())
.isEqualTo(com.mongodb.client.model.Collation.builder().locale("de").build()); .isEqualTo(com.mongodb.client.model.Collation.builder().locale("de").build());
} }
@ -128,11 +127,9 @@ public class DefaultBulkOperationsUnitTests {
ops.updateOne(query(where("firstName").is("danerys")), Update.update("firstName", "queen danerys")).execute(); ops.updateOne(query(where("firstName").is("danerys")), Update.update("firstName", "queen danerys")).execute();
ArgumentCaptor<List<WriteModel<Document>>> captor = ArgumentCaptor.forClass(List.class);
verify(collection).bulkWrite(captor.capture(), any()); verify(collection).bulkWrite(captor.capture(), any());
UpdateOneModel<Document> updateModel = (UpdateOneModel) captor.getValue().get(0); UpdateOneModel<Document> updateModel = (UpdateOneModel<Document>) captor.getValue().get(0);
assertThat(updateModel.getFilter()).isEqualTo(new Document("first_name", "danerys")); assertThat(updateModel.getFilter()).isEqualTo(new Document("first_name", "danerys"));
assertThat(updateModel.getUpdate()).isEqualTo(new Document("$set", new Document("first_name", "queen danerys"))); assertThat(updateModel.getUpdate()).isEqualTo(new Document("$set", new Document("first_name", "queen danerys")));
} }
@ -142,11 +139,9 @@ public class DefaultBulkOperationsUnitTests {
ops.remove(query(where("firstName").is("danerys"))).execute(); ops.remove(query(where("firstName").is("danerys"))).execute();
ArgumentCaptor<List<WriteModel<Document>>> captor = ArgumentCaptor.forClass(List.class);
verify(collection).bulkWrite(captor.capture(), any()); verify(collection).bulkWrite(captor.capture(), any());
DeleteManyModel<Document> updateModel = (DeleteManyModel) captor.getValue().get(0); DeleteManyModel<Document> updateModel = (DeleteManyModel<Document>) captor.getValue().get(0);
assertThat(updateModel.getFilter()).isEqualTo(new Document("first_name", "danerys")); assertThat(updateModel.getFilter()).isEqualTo(new Document("first_name", "danerys"));
} }

Loading…
Cancel
Save