Skip to content

Commit 49a3b56

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 #2242.
1 parent 2b249c3 commit 49a3b56

File tree

3 files changed

+54
-6
lines changed

3 files changed

+54
-6
lines changed

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

+12-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
import java.util.Map;
2626
import java.util.Optional;
2727
import java.util.function.Function;
28+
import java.util.stream.Collectors;
29+
import java.util.stream.StreamSupport;
2830

2931
import javax.persistence.EntityManager;
3032
import javax.persistence.LockModeType;
@@ -239,7 +241,16 @@ public void deleteAllByIdInBatch(Iterable<ID> ids) {
239241
entityInformation.getIdAttribute().getName());
240242

241243
Query query = em.createQuery(queryString);
242-
query.setParameter("ids", ids);
244+
/**
245+
* Some JPA providers require {@code ids} to be a {@link Collection} so we must convert if it's not already.
246+
*/
247+
if (Collection.class.isInstance(ids)) {
248+
query.setParameter("ids", ids);
249+
} else {
250+
Collection<ID> idsCollection = StreamSupport.stream(ids.spliterator(), false)
251+
.collect(Collectors.toCollection(ArrayList::new));
252+
query.setParameter("ids", idsCollection);
253+
}
243254

244255
query.executeUpdate();
245256
}

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
}

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

+33-1
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,17 @@
1818
import static org.assertj.core.api.Assertions.*;
1919

2020
import java.util.Arrays;
21+
import java.util.Iterator;
22+
import java.util.List;
2123
import java.util.Optional;
2224

2325
import javax.persistence.EntityManager;
2426
import javax.persistence.PersistenceContext;
2527

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)