Merge pull request #2504 from FOCONIS/sqlserver-delete-problem

Cannot delete bean with more than 2100 child beans on SqlServer
This commit is contained in:
Rob Bygrave
2022-01-27 08:54:27 +13:00
committed by GitHub
2 changed files with 28 additions and 1 deletions
@@ -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<Object> 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<Object> idList, Transaction transaction, DeleteMode deleteMode) {
SpiTransaction t = (SpiTransaction) transaction;
if (t.isPersistCascade()) {
BeanPropertyAssocOne<?>[] propImportDelete = descriptor.propertiesOneImportedDelete();
@@ -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<Contact> 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());