diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/RepositoryItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/RepositoryItemWriter.java index 5f5d18e15..51b188f57 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/RepositoryItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/RepositoryItemWriter.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -36,6 +36,8 @@ import org.springframework.util.MethodInvoker; *

* *

+ * By default, this writer will use {@link CrudRepository#saveAll(Iterable)} + * to save items, unless another method is selected with {@link #setMethodName(java.lang.String)}. * It depends on {@link org.springframework.data.repository.CrudRepository#saveAll(Iterable)} * method to store the items for the chunk. Performance will be determined by that * implementation more than this writer. @@ -107,6 +109,11 @@ public class RepositoryItemWriter implements ItemWriter, InitializingBean if (logger.isDebugEnabled()) { logger.debug("Writing to the repository with " + items.size() + " items."); } + + if (this.methodName == null) { + this.repository.saveAll(items); + return; + } MethodInvoker invoker = createMethodInvoker(repository, methodName); @@ -122,6 +129,12 @@ public class RepositoryItemWriter implements ItemWriter, InitializingBean @Override public void afterPropertiesSet() throws Exception { Assert.state(repository != null, "A CrudRepository implementation is required"); + if (this.methodName != null) { + Assert.hasText(this.methodName, "methodName must not be empty."); + } + else { + logger.debug("No method name provided, CrudRepository.saveAll will be used."); + } } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/RepositoryItemWriterBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/RepositoryItemWriterBuilder.java index da0109094..882b2dd64 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/RepositoryItemWriterBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/RepositoryItemWriterBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2018 the original author or authors. + * Copyright 2017-2020 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. @@ -19,6 +19,9 @@ package org.springframework.batch.item.data.builder; import java.lang.reflect.Method; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + import org.springframework.batch.item.data.RepositoryItemWriter; import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.MethodInterceptor; @@ -36,6 +39,8 @@ import org.springframework.util.Assert; */ public class RepositoryItemWriterBuilder { + private static final Log logger = LogFactory.getLog(RepositoryItemWriterBuilder.class.getName()); + private CrudRepository repository; private String methodName; @@ -104,12 +109,16 @@ public class RepositoryItemWriterBuilder { this.repository = this.repositoryMethodReference.getRepository(); } - Assert.hasText(this.methodName, "methodName is required."); Assert.notNull(this.repository, "repository is required."); RepositoryItemWriter writer = new RepositoryItemWriter<>(); - writer.setMethodName(this.methodName); writer.setRepository(this.repository); + if (this.methodName != null) { + Assert.hasText(this.methodName, "methodName must not be empty."); + writer.setMethodName(this.methodName); + } else { + logger.debug("No method name provided, CrudRepository.saveAll will be used."); + } return writer; } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/RepositoryItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/RepositoryItemWriterTests.java index 681ac5cd9..867377a4d 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/RepositoryItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/RepositoryItemWriterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2014 the original author or authors. + * Copyright 2013-2020 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. @@ -15,7 +15,9 @@ */ package org.springframework.batch.item.data; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; @@ -56,6 +58,17 @@ public class RepositoryItemWriterTests { fail(); } catch (IllegalStateException e) { } + + writer.setRepository(repository); + writer.setMethodName(""); + + try { + writer.afterPropertiesSet(); + fail("Expected IllegalArgumentException"); + } catch (IllegalArgumentException e) { + // expected + assertEquals("Wrong message for exception: " + e.getMessage(), "methodName must not be empty.", e.getMessage()); + } } @Test @@ -74,5 +87,16 @@ public class RepositoryItemWriterTests { writer.write(items); verify(repository).save("foo"); + verify(repository, never()).saveAll(items); + } + + @Test + public void testWriteItemsWithDefaultMethodName() throws Exception { + List items = Collections.singletonList("foo"); + + writer.setMethodName(null); + writer.write(items); + + verify(repository).saveAll(items); } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/RepositoryItemWriterBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/RepositoryItemWriterBuilderTests.java index 705f08aff..e529daae6 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/RepositoryItemWriterBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/RepositoryItemWriterBuilderTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 the original author or authors. + * Copyright 2017-2020 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. @@ -34,6 +34,7 @@ import static org.mockito.Mockito.verify; /** * @author Glenn Renfro + * @author Mahmoud Ben Hassine */ public class RepositoryItemWriterBuilderTests { @Mock @@ -58,15 +59,18 @@ public class RepositoryItemWriterBuilderTests { } @Test - public void testEmptyMethodName() throws Exception { + public void testEmptyMethodName() { try { - new RepositoryItemWriterBuilder().repository(this.repository).build(); + new RepositoryItemWriterBuilder() + .repository(this.repository) + .methodName("") + .build(); fail("IllegalArgumentException should have been thrown"); } catch (IllegalArgumentException iae) { assertEquals("IllegalArgumentException message did not match the expected result.", - "methodName is required.", iae.getMessage()); + "methodName must not be empty.", iae.getMessage()); } }