DATAES-142 - AbstractRepository.saveAll can process empty list.

Original PR: #307
This commit is contained in:
Peter-Josef Meisch 2019-08-18 21:04:11 +02:00
parent 4bb7b5ef56
commit b4ebca7ab5
4 changed files with 55 additions and 39 deletions

View File

@ -23,6 +23,7 @@ import java.util.ArrayList;
import java.util.Collections; 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 org.elasticsearch.ElasticsearchException; import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryBuilder;
@ -42,6 +43,7 @@ import org.springframework.data.elasticsearch.core.query.MoreLikeThisQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery; import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.data.util.Streamable;
import org.springframework.util.Assert; import org.springframework.util.Assert;
/** /**
@ -57,6 +59,7 @@ import org.springframework.util.Assert;
* @author Michael Wirth * @author Michael Wirth
* @author Sascha Woo * @author Sascha Woo
* @author Murali Chevuri * @author Murali Chevuri
* @author Peter-Josef Meisch
*/ */
public abstract class AbstractElasticsearchRepository<T, ID> implements ElasticsearchRepository<T, ID> { public abstract class AbstractElasticsearchRepository<T, ID> implements ElasticsearchRepository<T, ID> {
@ -182,16 +185,8 @@ public abstract class AbstractElasticsearchRepository<T, ID> implements Elastics
public <S extends T> List<S> save(List<S> entities) { public <S extends T> List<S> save(List<S> entities) {
Assert.notNull(entities, "Cannot insert 'null' as a List."); Assert.notNull(entities, "Cannot insert 'null' as a List.");
Assert.notEmpty(entities, "Cannot insert empty List.");
List<IndexQuery> queries = new ArrayList<>(); return Streamable.of(saveAll(entities)).stream().collect(Collectors.toList());
for (S s : entities) {
queries.add(createIndexQuery(s));
}
elasticsearchOperations.bulkIndex(queries);
elasticsearchOperations.refresh(entityInformation.getIndexName());
return entities;
} }
@Override @Override
@ -215,12 +210,13 @@ public abstract class AbstractElasticsearchRepository<T, ID> implements Elastics
Assert.notNull(entities, "Cannot insert 'null' as a List."); Assert.notNull(entities, "Cannot insert 'null' as a List.");
List<IndexQuery> queries = new ArrayList<>(); List<IndexQuery> queries = Streamable.of(entities).stream().map(this::createIndexQuery)
for (S s : entities) { .collect(Collectors.toList());
queries.add(createIndexQuery(s));
if (!queries.isEmpty()) {
elasticsearchOperations.bulkIndex(queries);
elasticsearchOperations.refresh(entityInformation.getIndexName());
} }
elasticsearchOperations.bulkIndex(queries);
elasticsearchOperations.refresh(entityInformation.getIndexName());
return entities; return entities;
} }

View File

@ -40,10 +40,10 @@ import org.elasticsearch.action.support.WriteRequest.RefreshPolicy;
import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.client.RestHighLevelClient;
import org.junit.Before; import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.reactivestreams.Publisher; import org.reactivestreams.Publisher;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.data.annotation.Id; import org.springframework.data.annotation.Id;
@ -52,6 +52,7 @@ import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Order; import org.springframework.data.domain.Sort.Order;
import org.springframework.data.elasticsearch.TestNodeResource;
import org.springframework.data.elasticsearch.TestUtils; import org.springframework.data.elasticsearch.TestUtils;
import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field; import org.springframework.data.elasticsearch.annotations.Field;
@ -67,12 +68,14 @@ import org.springframework.util.StringUtils;
/** /**
* @author Christoph Strobl * @author Christoph Strobl
* @currentRead Fool's Fate - Robin Hobb * @author Peter-Josef Meisch
*/ */
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)
@ContextConfiguration @ContextConfiguration
public class SimpleReactiveElasticsearchRepositoryTests { public class SimpleReactiveElasticsearchRepositoryTests {
@ClassRule public static TestNodeResource testNodeResource = new TestNodeResource();
@Configuration @Configuration
@EnableReactiveElasticsearchRepositories(considerNestedRepositories = true) @EnableReactiveElasticsearchRepositories(considerNestedRepositories = true)
static class Config extends AbstractReactiveElasticsearchConfiguration { static class Config extends AbstractReactiveElasticsearchConfiguration {

View File

@ -28,11 +28,13 @@ import lombok.NoArgsConstructor;
import java.lang.Long; import java.lang.Long;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; 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 org.elasticsearch.action.ActionRequestValidationException; import org.elasticsearch.action.ActionRequestValidationException;
import org.junit.Before; import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -42,12 +44,15 @@ import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Order; import org.springframework.data.domain.Sort.Order;
import org.springframework.data.elasticsearch.RestElasticsearchTestConfiguration;
import org.springframework.data.elasticsearch.TestNodeResource;
import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field; import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate; import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery; import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;
import org.springframework.data.elasticsearch.utils.IndexInitializer; import org.springframework.data.elasticsearch.utils.IndexInitializer;
import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.junit4.SpringRunner;
@ -62,16 +67,19 @@ import org.springframework.test.context.junit4.SpringRunner;
* @author Murali Chevuri * @author Murali Chevuri
*/ */
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)
@ContextConfiguration("classpath:/simple-repository-test.xml") @ContextConfiguration(classes = { SimpleElasticsearchRepositoryTests.class, RestElasticsearchTestConfiguration.class })
@EnableElasticsearchRepositories(considerNestedRepositories = true)
public class SimpleElasticsearchRepositoryTests { public class SimpleElasticsearchRepositoryTests {
@ClassRule public static TestNodeResource testNodeResource = new TestNodeResource();
@Autowired private SampleElasticsearchRepository repository; @Autowired private SampleElasticsearchRepository repository;
@Autowired private ElasticsearchTemplate elasticsearchTemplate; @Autowired private ElasticsearchOperations elasticsearchOperations;
@Before @Before
public void before() { public void before() {
IndexInitializer.init(elasticsearchTemplate, SampleEntity.class); IndexInitializer.init(elasticsearchOperations, SampleEntity.class);
} }
@Test @Test
@ -636,6 +644,34 @@ public class SimpleElasticsearchRepositoryTests {
assertThat(results.getTotalElements()).isGreaterThanOrEqualTo(1L); assertThat(results.getTotalElements()).isGreaterThanOrEqualTo(1L);
} }
@Test // DATAES-142
public void shouldIndexNotEmptyList() {
// given
List<SampleEntity> list = new ArrayList<>();
String documentId = randomNumeric(5);
SampleEntity sampleEntity1 = new SampleEntity();
sampleEntity1.setId(documentId);
sampleEntity1.setMessage("world");
list.add(sampleEntity1);
String documentId2 = randomNumeric(5);
SampleEntity sampleEntity2 = new SampleEntity();
sampleEntity2.setId(documentId2);
sampleEntity2.setMessage("hello");
list.add(sampleEntity2);
Iterable<SampleEntity> savedEntities = repository.saveAll(list);
assertThat(savedEntities).containsExactlyElementsOf(list);
}
@Test // DATAES-142
public void shouldNotFailOnIndexingEmptyList() {
Iterable<SampleEntity> savedEntities = repository.saveAll(Collections.emptyList());
assertThat(savedEntities).hasSize(0);
}
private static List<SampleEntity> createSampleEntitiesWithMessage(String message, int numberOfEntities) { private static List<SampleEntity> createSampleEntitiesWithMessage(String message, int numberOfEntities) {
List<SampleEntity> sampleEntities = new ArrayList<>(); List<SampleEntity> sampleEntities = new ArrayList<>();
for (int i = 0; i < numberOfEntities; i++) { for (int i = 0; i < numberOfEntities; i++) {

View File

@ -1,19 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:elasticsearch="http://www.springframework.org/schema/data/elasticsearch"
xsi:schemaLocation="http://www.springframework.org/schema/data/elasticsearch https://www.springframework.org/schema/data/elasticsearch/spring-elasticsearch.xsd
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<import resource="infrastructure.xml"/>
<bean name="elasticsearchTemplate"
class="org.springframework.data.elasticsearch.core.ElasticsearchTemplate">
<constructor-arg name="client" ref="client"/>
</bean>
<elasticsearch:repositories
base-package="org.springframework.data.elasticsearch.repository.support.simple"
consider-nested-repositories="true"/>
</beans>