Skip to content

Commit 38457e6

Browse files
schaudermp911de
authored andcommitted
DATAJPA-1818 - Implements CrudRepository.deleteAllById(Iterable<ID> ids).
Handling of IN-Queries in Eclipselink is still broken so this properly works only with Hibernate. Original pull request: #435.
1 parent e2db961 commit 38457e6

File tree

6 files changed

+94
-16
lines changed

6 files changed

+94
-16
lines changed

src/main/java/org/springframework/data/jpa/repository/JpaRepository.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,19 @@ public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>,
8484
*/
8585
void deleteInBatch(Iterable<T> entities);
8686

87+
88+
/**
89+
* Deletes the entities identified by the given ids using a single {@link Query}.
90+
*
91+
* This kind of operation leaves JPAs first level cache and the database out of sync.
92+
* Consider flushing the `EntityManager` before calling this method.
93+
*
94+
* @param ids
95+
*
96+
* @since 3.0
97+
*/
98+
void deleteAllByIdInBatch(Iterable<ID> ids);
99+
87100
/**
88101
* Deletes all entities in a batch call.
89102
*/

src/main/java/org/springframework/data/jpa/repository/query/QueryUtils.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ public abstract class QueryUtils {
8686

8787
public static final String COUNT_QUERY_STRING = "select count(%s) from %s x";
8888
public static final String DELETE_ALL_QUERY_STRING = "delete from %s x";
89+
public static final String DELETE_ALL_QUERY_BY_ID_STRING = "delete from %s x where %s in :ids";
8990

9091
// Used Regex/Unicode categories (see https://www.unicode.org/reports/tr18/#General_Category_Property):
9192
// Z Separator

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,16 @@ public void deleteAll(Iterable<? extends T> entities) {
218218
}
219219
}
220220

221+
@Override
222+
public void deleteAllById(Iterable<? extends ID> ids) {
223+
224+
Assert.notNull(ids, "Ids must not be null!");
225+
226+
for (ID id : ids) {
227+
deleteById(id);
228+
}
229+
}
230+
221231
/*
222232
* (non-Javadoc)
223233
* @see org.springframework.data.jpa.repository.JpaRepository#deleteInBatch(java.lang.Iterable)
@@ -236,6 +246,24 @@ public void deleteInBatch(Iterable<T> entities) {
236246
.executeUpdate();
237247
}
238248

249+
@Override
250+
public void deleteAllByIdInBatch(Iterable<ID> ids) {
251+
252+
Assert.notNull(ids, "Ids must not be null!");
253+
254+
if (!ids.iterator().hasNext()) {
255+
return;
256+
}
257+
258+
String queryTemplate = DELETE_ALL_QUERY_BY_ID_STRING;
259+
String queryString = String.format(queryTemplate, entityInformation.getEntityName(), entityInformation.getIdAttribute().getName());
260+
261+
Query query = em.createQuery(queryString);
262+
query.setParameter("ids", ids);
263+
264+
query.executeUpdate();
265+
}
266+
239267
/*
240268
* (non-Javadoc)
241269
* @see org.springframework.data.repository.Repository#deleteAll()

src/test/java/org/springframework/data/jpa/repository/UserRepositoryTests.java

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package org.springframework.data.jpa.repository;
1717

18+
import static java.util.Arrays.*;
1819
import static org.assertj.core.api.Assertions.*;
1920
import static org.springframework.data.domain.Example.*;
2021
import static org.springframework.data.domain.ExampleMatcher.*;
@@ -151,7 +152,7 @@ void findsAllByGivenIds() {
151152

152153
flushTestUsers();
153154

154-
assertThat(repository.findAllById(Arrays.asList(firstUser.getId(), secondUser.getId()))).contains(firstUser,
155+
assertThat(repository.findAllById(asList(firstUser.getId(), secondUser.getId()))).contains(firstUser,
155156
secondUser);
156157
}
157158

@@ -166,7 +167,7 @@ void testReadByIdReturnsNullForNotFoundEntities() {
166167
@Test
167168
void savesCollectionCorrectly() throws Exception {
168169

169-
assertThat(repository.saveAll(Arrays.asList(firstUser, secondUser, thirdUser))).hasSize(3).contains(firstUser,
170+
assertThat(repository.saveAll(asList(firstUser, secondUser, thirdUser))).hasSize(3).contains(firstUser,
170171
secondUser, thirdUser);
171172
}
172173

@@ -238,27 +239,41 @@ void returnsAllIgnoreCaseSortedCorrectly() throws Exception {
238239
}
239240

240241
@Test
241-
void deleteColletionOfEntities() {
242+
void deleteCollectionOfEntities() {
242243

243244
flushTestUsers();
244245

245246
long before = repository.count();
246247

247-
repository.deleteAll(Arrays.asList(firstUser, secondUser));
248+
repository.deleteAll(asList(firstUser, secondUser));
248249

249250
assertThat(repository.existsById(firstUser.getId())).isFalse();
250251
assertThat(repository.existsById(secondUser.getId())).isFalse();
251252
assertThat(repository.count()).isEqualTo(before - 2);
252253
}
253254

254255
@Test
255-
void batchDeleteColletionOfEntities() {
256+
void batchDeleteCollectionOfEntities() {
256257

257258
flushTestUsers();
258259

259260
long before = repository.count();
260261

261-
repository.deleteInBatch(Arrays.asList(firstUser, secondUser));
262+
repository.deleteInBatch(asList(firstUser, secondUser));
263+
264+
assertThat(repository.existsById(firstUser.getId())).isFalse();
265+
assertThat(repository.existsById(secondUser.getId())).isFalse();
266+
assertThat(repository.count()).isEqualTo(before - 2);
267+
}
268+
269+
@Test // DATAJPA-1818
270+
void deleteCollectionOfEntitiesById() {
271+
272+
flushTestUsers();
273+
274+
long before = repository.count();
275+
276+
repository.deleteAllById(asList(firstUser.getId(), secondUser.getId()));
262277

263278
assertThat(repository.existsById(firstUser.getId())).isFalse();
264279
assertThat(repository.existsById(secondUser.getId())).isFalse();
@@ -603,7 +618,7 @@ void executesQueryMethodWithDeepTraversalCorrectly() throws Exception {
603618

604619
firstUser.setManager(secondUser);
605620
thirdUser.setManager(firstUser);
606-
repository.saveAll(Arrays.asList(firstUser, thirdUser));
621+
repository.saveAll(asList(firstUser, thirdUser));
607622

608623
assertThat(repository.findByManagerLastname("Arrasz")).containsOnly(firstUser);
609624
assertThat(repository.findByManagerLastname("Gierke")).containsOnly(thirdUser);
@@ -616,7 +631,7 @@ void executesFindByColleaguesLastnameCorrectly() throws Exception {
616631

617632
firstUser.addColleague(secondUser);
618633
thirdUser.addColleague(firstUser);
619-
repository.saveAll(Arrays.asList(firstUser, thirdUser));
634+
repository.saveAll(asList(firstUser, thirdUser));
620635

621636
assertThat(repository.findByColleaguesLastname(secondUser.getLastname())).containsOnly(firstUser);
622637

@@ -1178,7 +1193,7 @@ void findByElementCollectionAttribute() {
11781193

11791194
flushTestUsers();
11801195

1181-
List<User> result = repository.findByAttributesIn(new HashSet<>(Arrays.asList("cool", "hip")));
1196+
List<User> result = repository.findByAttributesIn(new HashSet<>(asList("cool", "hip")));
11821197

11831198
assertThat(result).containsOnly(firstUser, secondUser);
11841199
}
@@ -1731,7 +1746,7 @@ void findAllByExampleWithAssociation() {
17311746

17321747
firstUser.setManager(secondUser);
17331748
thirdUser.setManager(firstUser);
1734-
repository.saveAll(Arrays.asList(firstUser, thirdUser));
1749+
repository.saveAll(asList(firstUser, thirdUser));
17351750

17361751
User manager = new User();
17371752
manager.setLastname("Arrasz");
@@ -1854,7 +1869,7 @@ void findAllByExampleWithIncludeNull() {
18541869
fifthUser.setFirstname(firstUser.getFirstname());
18551870
fifthUser.setLastname(firstUser.getLastname());
18561871

1857-
repository.saveAll(Arrays.asList(firstUser, fifthUser));
1872+
repository.saveAll(asList(firstUser, fifthUser));
18581873

18591874
User prototype = new User();
18601875
prototype.setFirstname(firstUser.getFirstname());
@@ -2242,7 +2257,7 @@ void findByElementCollectionInAttributeIgnoreCase() {
22422257

22432258
flushTestUsers();
22442259

2245-
List<User> result = repository.findByAttributesIgnoreCaseIn(new HashSet<>(Arrays.asList("cOOl", "hIP")));
2260+
List<User> result = repository.findByAttributesIgnoreCaseIn(new HashSet<>(asList("cOOl", "hIP")));
22462261

22472262
assertThat(result).containsOnly(firstUser, secondUser);
22482263
}
@@ -2256,7 +2271,7 @@ void findByElementCollectionNotInAttributeIgnoreCase() {
22562271

22572272
flushTestUsers();
22582273

2259-
List<User> result = repository.findByAttributesIgnoreCaseNotIn(Arrays.asList("CooL", "HIp"));
2274+
List<User> result = repository.findByAttributesIgnoreCaseNotIn(asList("CooL", "HIp"));
22602275

22612276
assertThat(result).containsOnly(thirdUser);
22622277
}
@@ -2284,7 +2299,7 @@ void findByElementCollectionInAttributeIgnoreCaseWithNulls() {
22842299

22852300
flushTestUsers();
22862301

2287-
List<User> result = repository.findByAttributesIgnoreCaseIn(Arrays.asList("cOOl", null));
2302+
List<User> result = repository.findByAttributesIgnoreCaseIn(asList("cOOl", null));
22882303

22892304
assertThat(result).containsOnly(firstUser);
22902305
}

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package org.springframework.data.jpa.repository.support;
1717

18+
import org.junit.jupiter.api.Disabled;
1819
import org.springframework.test.context.ContextConfiguration;
1920

2021
/**
@@ -25,4 +26,11 @@
2526
@ContextConfiguration("classpath:eclipselink.xml")
2627
class EclipseLinkJpaRepositoryTests extends JpaRepositoryTests {
2728

29+
@Override
30+
/**
31+
* Ignored until https://bugs.eclipse.org/bugs/show_bug.cgi?id=349477 is resolved.
32+
*/
33+
void deleteAllByIdInBatch() {
34+
super.deleteAllByIdInBatch();
35+
}
2836
}

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

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,11 +114,24 @@ void executesExistsForEntityWithIdClass() {
114114
assertThat(idClassRepository.existsById(id)).isTrue();
115115
}
116116

117-
private static interface SampleEntityRepository extends JpaRepository<SampleEntity, SampleEntityPK> {
117+
@Test // DATAJPA-1818
118+
void deleteAllByIdInBatch() {
119+
120+
SampleEntity one = new SampleEntity("one", "eins");
121+
SampleEntity two = new SampleEntity("two", "zwei");
122+
SampleEntity three = new SampleEntity("three", "drei");
123+
repository.saveAll(Arrays.asList(one, two, three));
124+
repository.flush();
125+
126+
repository.deleteAllByIdInBatch(Arrays.asList(new SampleEntityPK("one", "eins"),new SampleEntityPK("three", "drei")));
127+
assertThat(repository.findAll()).containsExactly(two);
128+
}
129+
130+
private interface SampleEntityRepository extends JpaRepository<SampleEntity, SampleEntityPK> {
118131

119132
}
120133

121-
private static interface SampleWithIdClassRepository
134+
private interface SampleWithIdClassRepository
122135
extends CrudRepository<PersistableWithIdClass, PersistableWithIdClassPK> {
123136

124137
}

0 commit comments

Comments
 (0)