From 2e74c19995e40c8564e005ced66d73d22ea426ca Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Fri, 28 Nov 2014 17:48:43 +0100 Subject: [PATCH] DATAMONGO-1054 - Polishing. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tweaked JavaDoc of the APIs to be less specific about implementation internals and rather point to the save(…) methods. Changed SimpleMongoRepository.save(…) methods to inspect the given entity/entities and use the optimized insert(All)-calls if all entities are considered new. Original pull request: #253. --- .../mongodb/repository/MongoRepository.java | 24 +++--- .../support/QueryDslMongoRepository.java | 21 +++-- .../support/SimpleMongoRepository.java | 76 ++++++++++--------- .../support/SimpleMongoRepositoryTests.java | 6 +- 4 files changed, 65 insertions(+), 62 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/MongoRepository.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/MongoRepository.java index 5560f3b28..c056d61cb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/MongoRepository.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/MongoRepository.java @@ -51,28 +51,24 @@ public interface MongoRepository extends PagingAndSo List findAll(Sort sort); /** - * Saves a given entity. Use the returned instance for further operations as the save operation might have changed the - * entity instance completely. - *

- * This uses {@link org.springframework.data.mongodb.core.MongoTemplate#insert(Object)} for storing the given entity. - *

- * Note that this method does neither fire any save events nor performs any id population or version checking. + * Inserts the given a given entity. Assumes the instance to be new to be able to apply insertion optimizations. Use + * the returned instance for further operations as the save operation might have changed the entity instance + * completely. Prefer using {@link #save(Object)} instead to avoid the usage of store-specific API. * - * @param entity + * @param entity must not be {@literal null}. * @return the saved entity + * @since 1.7 */ S insert(S entity); /** - * Saves all given entities. - *

- * This uses {@link org.springframework.data.mongodb.core.MongoTemplate#insert(Object)} for storing the given entity. - *

- * Note that this method does neither fire any save events nor nor performs any id population or version checking. + * Inserts the given entities. Assumes the given entities to have not been persisted yet and thus will optimize the + * insert over a call to {@link #save(Iterable)}. Prefer using {@link #save(Iterable)} to avoid the usage of store + * specific API. * - * @param entities + * @param entities must not be {@literal null}. * @return the saved entities - * @throws IllegalArgumentException in case the given entity is (@literal null}. + * @since 1.7 */ List insert(Iterable entities); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QueryDslMongoRepository.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QueryDslMongoRepository.java index 8bb4dde24..35cf425eb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QueryDslMongoRepository.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QueryDslMongoRepository.java @@ -29,6 +29,7 @@ import org.springframework.data.mongodb.repository.query.MongoEntityInformation; import org.springframework.data.querydsl.EntityPathResolver; import org.springframework.data.querydsl.QueryDslPredicateExecutor; import org.springframework.data.querydsl.SimpleEntityPathResolver; +import org.springframework.data.repository.core.EntityInformation; import org.springframework.data.repository.core.EntityMetadata; import org.springframework.util.Assert; @@ -48,13 +49,15 @@ public class QueryDslMongoRepository extends SimpleM QueryDslPredicateExecutor { private final PathBuilder builder; + private final EntityInformation entityInformation; + private final MongoOperations mongoOperations; /** * Creates a new {@link QueryDslMongoRepository} for the given {@link EntityMetadata} and {@link MongoTemplate}. Uses * the {@link SimpleEntityPathResolver} to create an {@link EntityPath} for the given domain class. * - * @param entityInformation - * @param template + * @param entityInformation must not be {@literal null}. + * @param mongoOperations must not be {@literal null}. */ public QueryDslMongoRepository(MongoEntityInformation entityInformation, MongoOperations mongoOperations) { this(entityInformation, mongoOperations, SimpleEntityPathResolver.INSTANCE); @@ -64,17 +67,21 @@ public class QueryDslMongoRepository extends SimpleM * Creates a new {@link QueryDslMongoRepository} for the given {@link MongoEntityInformation}, {@link MongoTemplate} * and {@link EntityPathResolver}. * - * @param entityInformation - * @param mongoOperations - * @param resolver + * @param entityInformation must not be {@literal null}. + * @param mongoOperations must not be {@literal null}. + * @param resolver must not be {@literal null}. */ public QueryDslMongoRepository(MongoEntityInformation entityInformation, MongoOperations mongoOperations, EntityPathResolver resolver) { super(entityInformation, mongoOperations); + Assert.notNull(resolver); EntityPath path = resolver.createPath(entityInformation.getJavaType()); + this.builder = new PathBuilder(path.getType(), path.getMetadata()); + this.entityInformation = entityInformation; + this.mongoOperations = mongoOperations; } /* @@ -139,9 +146,9 @@ public class QueryDslMongoRepository extends SimpleM */ private MongodbQuery createQueryFor(Predicate... predicate) { - Class domainType = getEntityInformation().getJavaType(); + Class domainType = entityInformation.getJavaType(); - MongodbQuery query = new SpringDataMongodbQuery(getMongoOperations(), domainType); + MongodbQuery query = new SpringDataMongodbQuery(mongoOperations, domainType); return query.where(predicate); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java index 0377893ed..0b768343d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java @@ -72,7 +72,12 @@ public class SimpleMongoRepository implements MongoR Assert.notNull(entity, "Entity must not be null!"); - mongoOperations.save(entity, entityInformation.getCollectionName()); + if (entityInformation.isNew(entity)) { + mongoOperations.insert(entity, entityInformation.getCollectionName()); + } else { + mongoOperations.save(entity, entityInformation.getCollectionName()); + } + return entity; } @@ -84,11 +89,22 @@ public class SimpleMongoRepository implements MongoR Assert.notNull(entities, "The given Iterable of entities not be null!"); - List result = new ArrayList(tryDetermineRealSizeOrReturn(entities, 10)); + List result = convertIterableToList(entities); + boolean allNew = true; for (S entity : entities) { - save(entity); - result.add(entity); + if (allNew && !entityInformation.isNew(entity)) { + allNew = false; + } + } + + if (allNew) { + mongoOperations.insertAll(result); + } else { + + for (S entity : result) { + save(entity); + } } return result; @@ -211,32 +227,8 @@ public class SimpleMongoRepository implements MongoR return findAll(new Query().with(sort)); } - private List findAll(Query query) { - - if (query == null) { - return Collections.emptyList(); - } - - return mongoOperations.find(query, entityInformation.getJavaType(), entityInformation.getCollectionName()); - } - - /** - * Returns the underlying {@link MongoOperations} instance. - * - * @return - */ - protected MongoOperations getMongoOperations() { - return this.mongoOperations; - } - - /** - * @return the entityInformation - */ - protected MongoEntityInformation getEntityInformation() { - return entityInformation; - } - - /* (non-Javadoc) + /* + * (non-Javadoc) * @see org.springframework.data.mongodb.repository.MongoRepository#insert(java.lang.Object) */ @Override @@ -248,7 +240,8 @@ public class SimpleMongoRepository implements MongoR return entity; } - /* (non-Javadoc) + /* + * (non-Javadoc) * @see org.springframework.data.mongodb.repository.MongoRepository#insert(java.lang.Iterable) */ @Override @@ -266,27 +259,36 @@ public class SimpleMongoRepository implements MongoR return list; } - private List convertIterableToList(Iterable entities) { + private List findAll(Query query) { + + if (query == null) { + return Collections.emptyList(); + } + + return mongoOperations.find(query, entityInformation.getJavaType(), entityInformation.getCollectionName()); + } + + private static List convertIterableToList(Iterable entities) { if (entities instanceof List) { - return (List) entities; + return (List) entities; } int capacity = tryDetermineRealSizeOrReturn(entities, 10); if (capacity == 0 || entities == null) { - return Collections. emptyList(); + return Collections. emptyList(); } - List list = new ArrayList(capacity); - for (S entity : entities) { + List list = new ArrayList(capacity); + for (T entity : entities) { list.add(entity); } return list; } - private int tryDetermineRealSizeOrReturn(Iterable iterable, int defaultSize) { + private static int tryDetermineRealSizeOrReturn(Iterable iterable, int defaultSize) { return iterable == null ? 0 : (iterable instanceof Collection) ? ((Collection) iterable).size() : defaultSize; } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java index 2f8f6e75f..5e9177ae3 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java @@ -123,9 +123,9 @@ public class SimpleMongoRepositoryTests { public void shouldInsertMutlipleFromList() { String randomId = UUID.randomUUID().toString(); - Map idToPerson = new HashMap(); List persons = new ArrayList(); + for (int i = 0; i < 10; i++) { Person person = new Person("First" + i + randomId, "Last" + randomId + i, 42 + i); idToPerson.put(person.getId(), person); @@ -135,7 +135,6 @@ public class SimpleMongoRepositoryTests { List saved = repository.insert(persons); assertThat(saved, hasSize(persons.size())); - assertThatAllReferencePersonsWereStoredCorrectly(idToPerson, saved); } @@ -146,9 +145,9 @@ public class SimpleMongoRepositoryTests { public void shouldInsertMutlipleFromSet() { String randomId = UUID.randomUUID().toString(); - Map idToPerson = new HashMap(); Set persons = new HashSet(); + for (int i = 0; i < 10; i++) { Person person = new Person("First" + i + randomId, "Last" + i + randomId, 42 + i); idToPerson.put(person.getId(), person); @@ -158,7 +157,6 @@ public class SimpleMongoRepositoryTests { List saved = repository.insert(persons); assertThat(saved, hasSize(persons.size())); - assertThatAllReferencePersonsWereStoredCorrectly(idToPerson, saved); }