From c053f08d6565692172a073247c97f41b0f2d5b03 Mon Sep 17 00:00:00 2001 From: "Greg L. Turnquist" Date: Wed, 13 Apr 2022 11:01:19 -0500 Subject: [PATCH] Convert Iterable to Collection for deleteAllByIdInBatch. JpaRepository accepts Iterable for bulk deletes. But some JPA providers require Collection instead. To avoid breaking any APIs, convert the incoming argument if it's not already a Collection. See #2242. --- .../support/SimpleJpaRepository.java | 13 +++++- .../EclipseLinkJpaRepositoryTests.java | 13 ++++-- .../support/JpaRepositoryTests.java | 40 +++++++++++++++++-- 3 files changed, 57 insertions(+), 9 deletions(-) diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java index f98555f8c..ebdec761b 100644 --- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java +++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java @@ -38,6 +38,8 @@ import java.util.List; import java.util.Map; import java.util.Optional; import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.data.domain.Example; @@ -223,7 +225,16 @@ public class SimpleJpaRepository implements JpaRepositoryImplementation idsCollection = StreamSupport.stream(ids.spliterator(), false) + .collect(Collectors.toCollection(ArrayList::new)); + query.setParameter("ids", idsCollection); + } query.executeUpdate(); } diff --git a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/support/EclipseLinkJpaRepositoryTests.java b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/support/EclipseLinkJpaRepositoryTests.java index 2574770e7..bb16ec76c 100644 --- a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/support/EclipseLinkJpaRepositoryTests.java +++ b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/support/EclipseLinkJpaRepositoryTests.java @@ -22,15 +22,20 @@ import org.springframework.test.context.ContextConfiguration; * Integration tests to execute {@link JpaRepositoryTests} against EclipseLink. * * @author Oliver Gierke + * @author Greg Turnquist */ @ContextConfiguration("classpath:eclipselink.xml") class EclipseLinkJpaRepositoryTests extends JpaRepositoryTests { @Override - /** - * Ignored until https://bugs.eclipse.org/bugs/show_bug.cgi?id=349477 is resolved. - */ + @Disabled("https://bugs.eclipse.org/bugs/show_bug.cgi?id=349477") void deleteAllByIdInBatch() { - super.deleteAllByIdInBatch(); + // disabled + } + + @Override + @Disabled("https://bugs.eclipse.org/bugs/show_bug.cgi?id=349477") + void deleteAllByIdInBatchShouldConvertAnIterableToACollection() { + // disabled } } diff --git a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/support/JpaRepositoryTests.java b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/support/JpaRepositoryTests.java index ea5e17917..9b5860e1d 100644 --- a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/support/JpaRepositoryTests.java +++ b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/support/JpaRepositoryTests.java @@ -17,16 +17,18 @@ package org.springframework.data.jpa.repository.support; import static org.assertj.core.api.Assertions.*; -import java.util.Arrays; -import java.util.Optional; - import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Optional; + +import org.jetbrains.annotations.NotNull; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; - import org.springframework.data.jpa.domain.sample.PersistableWithIdClass; import org.springframework.data.jpa.domain.sample.PersistableWithIdClassPK; import org.springframework.data.jpa.domain.sample.SampleEntity; @@ -43,6 +45,7 @@ import org.springframework.transaction.annotation.Transactional; * @author Oliver Gierke * @author Thomas Darimont * @author Jens Schauder + * @author Greg Turnquist */ @ExtendWith(SpringExtension.class) @ContextConfiguration({ "classpath:infrastructure.xml" }) @@ -128,6 +131,35 @@ class JpaRepositoryTests { assertThat(repository.findAll()).containsExactly(two); } + @Test // GH-2242 + void deleteAllByIdInBatchShouldConvertAnIterableToACollection() { + + SampleEntity one = new SampleEntity("one", "eins"); + SampleEntity two = new SampleEntity("two", "zwei"); + SampleEntity three = new SampleEntity("three", "drei"); + repository.saveAll(Arrays.asList(one, two, three)); + repository.flush(); + + /** + * Wrap a {@link List} inside an {@link Iterable} to verify that {@link SimpleJpaRepository} can properly convert a + * pure {@link Iterable} to a {@link Collection}. + **/ + Iterable ids = new Iterable() { + + private List ids = Arrays.asList(new SampleEntityPK("one", "eins"), + new SampleEntityPK("three", "drei")); + + @NotNull + @Override + public Iterator iterator() { + return ids.iterator(); + } + }; + + repository.deleteAllByIdInBatch(ids); + assertThat(repository.findAll()).containsExactly(two); + } + private interface SampleEntityRepository extends JpaRepository { }