diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/persist/DefaultPersister.java b/ebean-core/src/main/java/io/ebeaninternal/server/persist/DefaultPersister.java index 701b76402..eaa1e1c95 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/persist/DefaultPersister.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/persist/DefaultPersister.java @@ -1,6 +1,7 @@ package io.ebeaninternal.server.persist; import io.ebean.*; +import io.ebean.annotation.Platform; import io.ebean.bean.BeanCollection; import io.ebean.bean.BeanCollection.ModifyListenMode; import io.ebean.bean.EntityBean; @@ -644,11 +645,25 @@ public final class DefaultPersister implements Persister { DeleteMode deleteMode = (permanent || !descriptor.isSoftDelete()) ? DeleteMode.HARD : DeleteMode.SOFT; return delete(descriptor, null, idList, transaction, deleteMode); } - + /** * Delete by Id or a List of Id's. */ private int delete(BeanDescriptor descriptor, Object id, List idList, Transaction transaction, DeleteMode deleteMode) { + int rows = 0; + if (server.databasePlatform().isPlatform(Platform.SQLSERVER)) { + // SqlServer has a 2100 parameter limit, so delete max 2000 ids at once + // this gives space up to 100 more query parameters. + while (idList != null && idList.size() > 2000) { + rows += deleteBatch(descriptor, id, idList.subList(0, 2000), transaction, deleteMode); + idList = idList.subList(2000, idList.size()); + } + } + rows += deleteBatch(descriptor, id, idList, transaction, deleteMode); + return rows; + } + + private int deleteBatch(BeanDescriptor descriptor, Object id, List idList, Transaction transaction, DeleteMode deleteMode) { SpiTransaction t = (SpiTransaction) transaction; if (t.isPersistCascade()) { BeanPropertyAssocOne[] propImportDelete = descriptor.propertiesOneImportedDelete(); diff --git a/ebean-test/src/test/java/org/tests/delete/TestDeleteByQuery.java b/ebean-test/src/test/java/org/tests/delete/TestDeleteByQuery.java index 4e826b584..8ff2ad54b 100644 --- a/ebean-test/src/test/java/org/tests/delete/TestDeleteByQuery.java +++ b/ebean-test/src/test/java/org/tests/delete/TestDeleteByQuery.java @@ -7,6 +7,7 @@ import io.ebean.test.LoggedSql; import org.junit.jupiter.api.Test; import org.tests.model.basic.*; +import java.util.ArrayList; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; @@ -233,6 +234,17 @@ public class TestDeleteByQuery extends BaseTestCase { DB.save(contact); + // check if we can delete more than 2100 in a batch on SqlServer + List moreContacts = new ArrayList<>(); + for (int i = 0; i < 2200; i++) { + Contact c = new Contact(); + c.setFirstName("DelByQueryFirstName"); + c.setLastName("deleteMe"); + c.setCustomer(all.get(0)); + moreContacts.add(c); + } + DB.saveAll(moreContacts); + DB.find(Contact.class).where().eq("firstName", "DelByQueryFirstName").delete(); Contact contactFind = DB.find(Contact.class, contact.getId());