Skip to content

Commit e4e2a25

Browse files
committed
fix: support compound IdClass ID's when calling deleteAllByIdInBatch
Convert ID's to entities and pass them to deleteAllInBatch. Issue: spring-projects#2414
1 parent 90ffd03 commit e4e2a25

File tree

2 files changed

+68
-30
lines changed

2 files changed

+68
-30
lines changed

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

+42-30
Original file line numberDiff line numberDiff line change
@@ -15,31 +15,6 @@
1515
*/
1616
package org.springframework.data.jpa.repository.support;
1717

18-
import static org.springframework.data.jpa.repository.query.QueryUtils.*;
19-
20-
import java.util.ArrayList;
21-
import java.util.Collection;
22-
import java.util.Collections;
23-
import java.util.HashMap;
24-
import java.util.List;
25-
import java.util.Map;
26-
import java.util.Optional;
27-
import java.util.function.Function;
28-
29-
import javax.persistence.EntityManager;
30-
import javax.persistence.LockModeType;
31-
import javax.persistence.NoResultException;
32-
import javax.persistence.Parameter;
33-
import javax.persistence.Query;
34-
import javax.persistence.TypedQuery;
35-
import javax.persistence.criteria.CriteriaBuilder;
36-
import javax.persistence.criteria.CriteriaQuery;
37-
import javax.persistence.criteria.Order;
38-
import javax.persistence.criteria.ParameterExpression;
39-
import javax.persistence.criteria.Path;
40-
import javax.persistence.criteria.Predicate;
41-
import javax.persistence.criteria.Root;
42-
4318
import org.springframework.dao.EmptyResultDataAccessException;
4419
import org.springframework.data.domain.Example;
4520
import org.springframework.data.domain.Page;
@@ -62,6 +37,35 @@
6237
import org.springframework.transaction.annotation.Transactional;
6338
import org.springframework.util.Assert;
6439

40+
import javax.persistence.EntityManager;
41+
import javax.persistence.LockModeType;
42+
import javax.persistence.NoResultException;
43+
import javax.persistence.Parameter;
44+
import javax.persistence.Query;
45+
import javax.persistence.TypedQuery;
46+
import javax.persistence.criteria.CriteriaBuilder;
47+
import javax.persistence.criteria.CriteriaQuery;
48+
import javax.persistence.criteria.Order;
49+
import javax.persistence.criteria.ParameterExpression;
50+
import javax.persistence.criteria.Path;
51+
import javax.persistence.criteria.Predicate;
52+
import javax.persistence.criteria.Root;
53+
import java.util.ArrayList;
54+
import java.util.Collection;
55+
import java.util.Collections;
56+
import java.util.HashMap;
57+
import java.util.List;
58+
import java.util.Map;
59+
import java.util.Optional;
60+
import java.util.function.Function;
61+
62+
import static org.springframework.data.jpa.repository.query.QueryUtils.COUNT_QUERY_STRING;
63+
import static org.springframework.data.jpa.repository.query.QueryUtils.DELETE_ALL_QUERY_BY_ID_STRING;
64+
import static org.springframework.data.jpa.repository.query.QueryUtils.DELETE_ALL_QUERY_STRING;
65+
import static org.springframework.data.jpa.repository.query.QueryUtils.applyAndBind;
66+
import static org.springframework.data.jpa.repository.query.QueryUtils.getQueryString;
67+
import static org.springframework.data.jpa.repository.query.QueryUtils.toOrders;
68+
6569
/**
6670
* Default implementation of the {@link org.springframework.data.repository.CrudRepository} interface. This will offer
6771
* you a more sophisticated interface than the plain {@link EntityManager} .
@@ -226,13 +230,21 @@ public void deleteAllByIdInBatch(Iterable<ID> ids) {
226230
return;
227231
}
228232

229-
String queryString = String.format(DELETE_ALL_QUERY_BY_ID_STRING, entityInformation.getEntityName(),
230-
entityInformation.getIdAttribute().getName());
233+
if (entityInformation.hasCompositeId()) {
234+
// XXX Hibernate just creates an empty Entity here when doing the getById. Others might do a real select
235+
// that would introduce a big performance penalty. See JavaDoc for getById.
236+
List<T> entities = new ArrayList<>();
237+
ids.forEach(id -> entities.add(getById(id)));
238+
deleteAllInBatch(entities);
239+
} else {
240+
String queryString = String.format(DELETE_ALL_QUERY_BY_ID_STRING, entityInformation.getEntityName(),
241+
entityInformation.getIdAttribute().getName());
231242

232-
Query query = em.createQuery(queryString);
233-
query.setParameter("ids", ids);
243+
Query query = em.createQuery(queryString);
244+
query.setParameter("ids", ids);
234245

235-
query.executeUpdate();
246+
query.executeUpdate();
247+
}
236248
}
237249

238250
/*

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

+26
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import java.util.Arrays;
2121
import java.util.List;
22+
import java.util.Optional;
2223

2324
import org.junit.jupiter.api.Test;
2425
import org.junit.jupiter.api.extension.ExtendWith;
@@ -41,6 +42,8 @@
4142
import org.springframework.test.context.junit.jupiter.SpringExtension;
4243
import org.springframework.transaction.annotation.Transactional;
4344

45+
import javax.persistence.EntityManager;
46+
4447
/**
4548
* Tests some usage variants of composite keys with spring data jpa.
4649
*
@@ -55,6 +58,7 @@ public class RepositoryWithCompositeKeyTests {
5558

5659
@Autowired EmployeeRepositoryWithIdClass employeeRepositoryWithIdClass;
5760
@Autowired EmployeeRepositoryWithEmbeddedId employeeRepositoryWithEmbeddedId;
61+
@Autowired EntityManager em;
5862

5963
/**
6064
* @see <a href="download.oracle.com/otn-pub/jcp/persistence-2_1-fr-eval-spec/JavaPersistence.pdf">Final JPA 2.0
@@ -126,6 +130,28 @@ void shouldSupportFindAllWithPageableAndEntityWithIdClass() throws Exception {
126130
assertThat(page.getTotalElements()).isEqualTo(1L);
127131
}
128132

133+
@Test
134+
void shouldSupportDeleteAllByIdInBatchWithIdClass() throws Exception {
135+
136+
IdClassExampleDepartment dep = new IdClassExampleDepartment();
137+
dep.setName("TestDepartment");
138+
dep.setDepartmentId(-1);
139+
140+
IdClassExampleEmployee emp = new IdClassExampleEmployee();
141+
emp.setDepartment(dep);
142+
emp = employeeRepositoryWithIdClass.save(emp);
143+
144+
IdClassExampleEmployeePK key = new IdClassExampleEmployeePK(emp.getEmpId(), dep.getDepartmentId());
145+
assertThat(employeeRepositoryWithIdClass.findById(key)).isNotEmpty();
146+
147+
employeeRepositoryWithIdClass.deleteAllByIdInBatch(Arrays.asList(key));
148+
149+
em.flush();
150+
em.clear();
151+
152+
assertThat(employeeRepositoryWithIdClass.findById(key)).isEmpty();
153+
}
154+
129155
@Test // DATAJPA-497
130156
void sortByEmbeddedPkFieldInCompositePkWithEmbeddedIdInQueryDsl() {
131157

0 commit comments

Comments
 (0)