Browse Source

DATAMONGO-1054 - Add support for fast insertion via MongoRepository.insert(..).

Introduced new insert(..) method variants on MongoRepositories that delegates to MongoTemplate.insert(..). This bypasses ID-population, save event generation and version checking and allows for fast insertion of bulk data.

Original pull request: #253.
pull/243/merge
Thomas Darimont 11 years ago committed by Oliver Gierke
parent
commit
a212b7566c
  1. 27
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/MongoRepository.java
  2. 61
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepository.java
  3. 86
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java

27
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/MongoRepository.java

@ -27,6 +27,7 @@ import org.springframework.data.repository.PagingAndSortingRepository; @@ -27,6 +27,7 @@ import org.springframework.data.repository.PagingAndSortingRepository;
*
* @author Oliver Gierke
* @author Christoph Strobl
* @author Thomas Darimont
*/
@NoRepositoryBean
public interface MongoRepository<T, ID extends Serializable> extends PagingAndSortingRepository<T, ID> {
@ -48,4 +49,30 @@ public interface MongoRepository<T, ID extends Serializable> extends PagingAndSo @@ -48,4 +49,30 @@ public interface MongoRepository<T, ID extends Serializable> extends PagingAndSo
* @see org.springframework.data.repository.PagingAndSortingRepository#findAll(org.springframework.data.domain.Sort)
*/
List<T> 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.
* <p>
* This uses {@link org.springframework.data.mongodb.core.MongoTemplate#insert(Object)} for storing the given entity.
* <p>
* Note that this method does neither fire any save events nor performs any id population or version checking.
*
* @param entity
* @return the saved entity
*/
<S extends T> S insert(S entity);
/**
* Saves all given entities.
* <p>
* This uses {@link org.springframework.data.mongodb.core.MongoTemplate#insert(Object)} for storing the given entity.
* <p>
* Note that this method does neither fire any save events nor nor performs any id population or version checking.
*
* @param entities
* @return the saved entities
* @throws IllegalArgumentException in case the given entity is (@literal null}.
*/
<S extends T> List<S> insert(Iterable<S> entities);
}

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

@ -19,6 +19,7 @@ import static org.springframework.data.mongodb.core.query.Criteria.*; @@ -19,6 +19,7 @@ import static org.springframework.data.mongodb.core.query.Criteria.*;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
@ -41,6 +42,7 @@ import org.springframework.util.Assert; @@ -41,6 +42,7 @@ import org.springframework.util.Assert;
*
* @author Oliver Gierke
* @author Christoph Strobl
* @author Thomas Darimont
*/
public class SimpleMongoRepository<T, ID extends Serializable> implements MongoRepository<T, ID> {
@ -48,7 +50,7 @@ public class SimpleMongoRepository<T, ID extends Serializable> implements MongoR @@ -48,7 +50,7 @@ public class SimpleMongoRepository<T, ID extends Serializable> implements MongoR
private final MongoEntityInformation<T, ID> entityInformation;
/**
* Creates a ew {@link SimpleMongoRepository} for the given {@link MongoEntityInformation} and {@link MongoTemplate}.
* Creates a new {@link SimpleMongoRepository} for the given {@link MongoEntityInformation} and {@link MongoTemplate}.
*
* @param metadata must not be {@literal null}.
* @param template must not be {@literal null}.
@ -82,7 +84,7 @@ public class SimpleMongoRepository<T, ID extends Serializable> implements MongoR @@ -82,7 +84,7 @@ public class SimpleMongoRepository<T, ID extends Serializable> implements MongoR
Assert.notNull(entities, "The given Iterable of entities not be null!");
List<S> result = new ArrayList<S>();
List<S> result = new ArrayList<S>(tryDetermineRealSizeOrReturn(entities, 10));
for (S entity : entities) {
save(entity);
@ -181,7 +183,7 @@ public class SimpleMongoRepository<T, ID extends Serializable> implements MongoR @@ -181,7 +183,7 @@ public class SimpleMongoRepository<T, ID extends Serializable> implements MongoR
*/
public Iterable<T> findAll(Iterable<ID> ids) {
Set<ID> parameters = new HashSet<ID>();
Set<ID> parameters = new HashSet<ID>(tryDetermineRealSizeOrReturn(ids, 10));
for (ID id : ids) {
parameters.add(id);
}
@ -234,4 +236,57 @@ public class SimpleMongoRepository<T, ID extends Serializable> implements MongoR @@ -234,4 +236,57 @@ public class SimpleMongoRepository<T, ID extends Serializable> implements MongoR
return entityInformation;
}
/* (non-Javadoc)
* @see org.springframework.data.mongodb.repository.MongoRepository#insert(java.lang.Object)
*/
@Override
public <S extends T> S insert(S entity) {
Assert.notNull(entity, "Entity must not be null!");
mongoOperations.insert(entity, entityInformation.getCollectionName());
return entity;
}
/* (non-Javadoc)
* @see org.springframework.data.mongodb.repository.MongoRepository#insert(java.lang.Iterable)
*/
@Override
public <S extends T> List<S> insert(Iterable<S> entities) {
Assert.notNull(entities, "The given Iterable of entities not be null!");
List<S> list = convertIterableToList(entities);
if (list.isEmpty()) {
return list;
}
mongoOperations.insertAll(list);
return list;
}
private <S extends T> List<S> convertIterableToList(Iterable<S> entities) {
if (entities instanceof List) {
return (List<S>) entities;
}
int capacity = tryDetermineRealSizeOrReturn(entities, 10);
if (capacity == 0 || entities == null) {
return Collections.<S> emptyList();
}
List<S> list = new ArrayList<S>(capacity);
for (S entity : entities) {
list.add(entity);
}
return list;
}
private int tryDetermineRealSizeOrReturn(Iterable<?> iterable, int defaultSize) {
return iterable == null ? 0 : (iterable instanceof Collection) ? ((Collection<?>) iterable).size() : defaultSize;
}
}

86
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2010-2012 the original author or authors.
* Copyright 2010-2014 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.
@ -16,10 +16,16 @@ @@ -16,10 +16,16 @@
package org.springframework.data.mongodb.repository.support;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import org.junit.Before;
import org.junit.Test;
@ -34,13 +40,13 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -34,13 +40,13 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author <a href="mailto:kowsercse@gmail.com">A. B. M. Kowser</a>
* @author Thomas Darimont
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:infrastructure.xml")
public class SimpleMongoRepositoryTests {
@Autowired
private MongoTemplate template;
@Autowired private MongoTemplate template;
private Person oliver, dave, carter, boyd, stefan, leroi, alicia;
private List<Person> all;
@ -69,7 +75,7 @@ public class SimpleMongoRepositoryTests { @@ -69,7 +75,7 @@ public class SimpleMongoRepositoryTests {
List<Person> result = repository.findAll();
assertThat(result, hasSize(all.size()));
}
@Test
public void findOneFromCustomCollectionName() {
Person result = repository.findOne(dave.getId());
@ -94,6 +100,76 @@ public class SimpleMongoRepositoryTests { @@ -94,6 +100,76 @@ public class SimpleMongoRepositoryTests {
assertThat(result, not(hasItem(dave)));
}
/**
* @see DATAMONGO-1054
*/
@Test
public void shouldInsertSingle() {
String randomId = UUID.randomUUID().toString();
Person person1 = new Person("First1" + randomId, "Last2" + randomId, 42);
person1 = repository.insert(person1);
Person saved = repository.findOne(person1.getId());
assertThat(saved, is(equalTo(person1)));
}
/**
* @see DATAMONGO-1054
*/
@Test
public void shouldInsertMutlipleFromList() {
String randomId = UUID.randomUUID().toString();
Map<String, Person> idToPerson = new HashMap<String, Person>();
List<Person> persons = new ArrayList<Person>();
for (int i = 0; i < 10; i++) {
Person person = new Person("First" + i + randomId, "Last" + randomId + i, 42 + i);
idToPerson.put(person.getId(), person);
persons.add(person);
}
List<Person> saved = repository.insert(persons);
assertThat(saved, hasSize(persons.size()));
assertThatAllReferencePersonsWereStoredCorrectly(idToPerson, saved);
}
/**
* @see DATAMONGO-1054
*/
@Test
public void shouldInsertMutlipleFromSet() {
String randomId = UUID.randomUUID().toString();
Map<String, Person> idToPerson = new HashMap<String, Person>();
Set<Person> persons = new HashSet<Person>();
for (int i = 0; i < 10; i++) {
Person person = new Person("First" + i + randomId, "Last" + i + randomId, 42 + i);
idToPerson.put(person.getId(), person);
persons.add(person);
}
List<Person> saved = repository.insert(persons);
assertThat(saved, hasSize(persons.size()));
assertThatAllReferencePersonsWereStoredCorrectly(idToPerson, saved);
}
private void assertThatAllReferencePersonsWereStoredCorrectly(Map<String, Person> references, List<Person> saved) {
for (Person person : saved) {
Person reference = references.get(person.getId());
assertThat(person, is(equalTo(reference)));
}
}
private static class CustomizedPersonInformation implements MongoEntityInformation<Person, String> {
@Override

Loading…
Cancel
Save