Skip to content

Commit c053f08

Browse files
committed
Convert Iterable<ID> to Collection<ID> for deleteAllByIdInBatch.
JpaRepository accepts Iterable<ID> for bulk deletes. But some JPA providers require Collection<ID> instead. To avoid breaking any APIs, convert the incoming argument if it's not already a Collection. See spring-projects#2242.
1 parent 500bdb8 commit c053f08

File tree

3 files changed

+57
-9
lines changed

3 files changed

+57
-9
lines changed

spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java

+12-1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
import java.util.Map;
3939
import java.util.Optional;
4040
import java.util.function.Function;
41+
import java.util.stream.Collectors;
42+
import java.util.stream.StreamSupport;
4143

4244
import org.springframework.dao.EmptyResultDataAccessException;
4345
import org.springframework.data.domain.Example;
@@ -223,7 +225,16 @@ public void deleteAllByIdInBatch(Iterable<ID> ids) {
223225
entityInformation.getIdAttribute().getName());
224226

225227
Query query = em.createQuery(queryString);
226-
query.setParameter("ids", ids);
228+
/**
229+
* Some JPA providers require {@code ids} to be a {@link Collection} so we must convert if it's not already.
230+
*/
231+
if (Collection.class.isInstance(ids)) {
232+
query.setParameter("ids", ids);
233+
} else {
234+
Collection<ID> idsCollection = StreamSupport.stream(ids.spliterator(), false)
235+
.collect(Collectors.toCollection(ArrayList::new));
236+
query.setParameter("ids", idsCollection);
237+
}
227238

228239
query.executeUpdate();
229240
}

spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/support/EclipseLinkJpaRepositoryTests.java

+9-4
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,20 @@
2222
* Integration tests to execute {@link JpaRepositoryTests} against EclipseLink.
2323
*
2424
* @author Oliver Gierke
25+
* @author Greg Turnquist
2526
*/
2627
@ContextConfiguration("classpath:eclipselink.xml")
2728
class EclipseLinkJpaRepositoryTests extends JpaRepositoryTests {
2829

2930
@Override
30-
/**
31-
* Ignored until https://bugs.eclipse.org/bugs/show_bug.cgi?id=349477 is resolved.
32-
*/
31+
@Disabled("https://bugs.eclipse.org/bugs/show_bug.cgi?id=349477")
3332
void deleteAllByIdInBatch() {
34-
super.deleteAllByIdInBatch();
33+
// disabled
34+
}
35+
36+
@Override
37+
@Disabled("https://bugs.eclipse.org/bugs/show_bug.cgi?id=349477")
38+
void deleteAllByIdInBatchShouldConvertAnIterableToACollection() {
39+
// disabled
3540
}
3641
}

spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/support/JpaRepositoryTests.java

+36-4
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,18 @@
1717

1818
import static org.assertj.core.api.Assertions.*;
1919

20-
import java.util.Arrays;
21-
import java.util.Optional;
22-
2320
import jakarta.persistence.EntityManager;
2421
import jakarta.persistence.PersistenceContext;
2522

23+
import java.util.Arrays;
24+
import java.util.Iterator;
25+
import java.util.List;
26+
import java.util.Optional;
27+
28+
import org.jetbrains.annotations.NotNull;
2629
import org.junit.jupiter.api.BeforeEach;
2730
import org.junit.jupiter.api.Test;
2831
import org.junit.jupiter.api.extension.ExtendWith;
29-
3032
import org.springframework.data.jpa.domain.sample.PersistableWithIdClass;
3133
import org.springframework.data.jpa.domain.sample.PersistableWithIdClassPK;
3234
import org.springframework.data.jpa.domain.sample.SampleEntity;
@@ -43,6 +45,7 @@
4345
* @author Oliver Gierke
4446
* @author Thomas Darimont
4547
* @author Jens Schauder
48+
* @author Greg Turnquist
4649
*/
4750
@ExtendWith(SpringExtension.class)
4851
@ContextConfiguration({ "classpath:infrastructure.xml" })
@@ -128,6 +131,35 @@ void deleteAllByIdInBatch() {
128131
assertThat(repository.findAll()).containsExactly(two);
129132
}
130133

134+
@Test // GH-2242
135+
void deleteAllByIdInBatchShouldConvertAnIterableToACollection() {
136+
137+
SampleEntity one = new SampleEntity("one", "eins");
138+
SampleEntity two = new SampleEntity("two", "zwei");
139+
SampleEntity three = new SampleEntity("three", "drei");
140+
repository.saveAll(Arrays.asList(one, two, three));
141+
repository.flush();
142+
143+
/**
144+
* Wrap a {@link List} inside an {@link Iterable} to verify that {@link SimpleJpaRepository} can properly convert a
145+
* pure {@link Iterable} to a {@link Collection}.
146+
**/
147+
Iterable<SampleEntityPK> ids = new Iterable<SampleEntityPK>() {
148+
149+
private List<SampleEntityPK> ids = Arrays.asList(new SampleEntityPK("one", "eins"),
150+
new SampleEntityPK("three", "drei"));
151+
152+
@NotNull
153+
@Override
154+
public Iterator<SampleEntityPK> iterator() {
155+
return ids.iterator();
156+
}
157+
};
158+
159+
repository.deleteAllByIdInBatch(ids);
160+
assertThat(repository.findAll()).containsExactly(two);
161+
}
162+
131163
private interface SampleEntityRepository extends JpaRepository<SampleEntity, SampleEntityPK> {
132164

133165
}

0 commit comments

Comments
 (0)