Skip to content

Commit

Permalink
Merge pull request #3113 from FOCONIS/bugfix/batch_ordering_many2many…
Browse files Browse the repository at this point in the history
…_intersection

Bugfix for wrong batch statement ordering with many2many relations
  • Loading branch information
rbygrave authored Jun 16, 2023
2 parents 53b1e4d + b63445e commit ac1b307
Show file tree
Hide file tree
Showing 8 changed files with 39 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ public interface Persister {
/**
* Execute or queue the update.
*/
void executeOrQueue(SpiSqlUpdate update, SpiTransaction t, boolean queue);
void executeOrQueue(SpiSqlUpdate update, SpiTransaction t, boolean queue, int queuePosition);

/**
* Queue the SqlUpdate for execution with position 0, 1 or 2 defining
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ public final class BatchControl {

private final Queue[] queues = new Queue[3];

static final int DELETE_QUEUE = 1;
static final int INSERT_QUEUE = 2;

/**
* Create for a given transaction, PersistExecute, default size and getGeneratedKeys.
*/
Expand Down Expand Up @@ -267,8 +270,8 @@ public void clear() {
private void flushBuffer(boolean reset) throws BatchedSqlException {
flushQueue(queues[0]);
flushInternal(reset);
flushQueue(queues[1]);
flushQueue(queues[2]);
flushQueue(queues[DELETE_QUEUE]);
flushQueue(queues[INSERT_QUEUE]);
}

private void flushQueue(Queue queue) throws BatchedSqlException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,9 @@ public int[] executeBatch(SpiSqlUpdate sqlUpdate, SpiTransaction transaction) {
}

@Override
public void executeOrQueue(SpiSqlUpdate update, SpiTransaction t, boolean queue) {
public void executeOrQueue(SpiSqlUpdate update, SpiTransaction t, boolean queue, int queuePosition) {
if (queue) {
addToFlushQueue(update, t, 2);
addToFlushQueue(update, t, queuePosition);
} else {
executeSqlUpdate(update, t);
}
Expand Down Expand Up @@ -907,7 +907,7 @@ private SaveManyBase saveManyRequest(boolean insertedParent, BeanPropertyAssocMa
void deleteManyIntersection(EntityBean bean, BeanPropertyAssocMany<?> many, SpiTransaction t, boolean publish, boolean queue) {
SpiSqlUpdate sqlDelete = deleteAllIntersection(bean, many, publish);
if (queue) {
addToFlushQueue(sqlDelete, t, 1);
addToFlushQueue(sqlDelete, t, BatchControl.DELETE_QUEUE);
} else {
executeSqlUpdate(sqlDelete, t);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ abstract class SaveManyBase implements SaveMany {
final void preElementCollectionUpdate() {
if (!insertedParent) {
request.preElementCollectionUpdate();
persister.addToFlushQueue(many.deleteByParentId(request.beanId(), null), transaction, 1);
persister.addToFlushQueue(many.deleteByParentId(request.beanId(), null), transaction, BatchControl.DELETE_QUEUE);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ private void saveAssocManyIntersection(boolean queue) {
// build a intersection row for 'delete'
IntersectionRow intRow = many.buildManyToManyMapBean(parentBean, otherDelete, publish);
SpiSqlUpdate sqlDelete = intRow.createDelete(server, DeleteMode.HARD);
persister.executeOrQueue(sqlDelete, transaction, queue);
persister.executeOrQueue(sqlDelete, transaction, queue, BatchControl.DELETE_QUEUE);
}
}
if (additions != null && !additions.isEmpty()) {
Expand All @@ -314,7 +314,7 @@ private void saveAssocManyIntersection(boolean queue) {
// build a intersection row for 'insert'
IntersectionRow intRow = many.buildManyToManyMapBean(parentBean, otherBean, publish);
SpiSqlUpdate sqlInsert = intRow.createInsert(server);
persister.executeOrQueue(sqlInsert, transaction, queue);
persister.executeOrQueue(sqlInsert, transaction, queue, BatchControl.INSERT_QUEUE);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ private void saveCollection() {
final SpiSqlUpdate sqlInsert = proto.copy();
sqlInsert.setParameter(parentId);
many.bindElementValue(sqlInsert, value);
persister.addToFlushQueue(sqlInsert, transaction, 2);
persister.addToFlushQueue(sqlInsert, transaction, BatchControl.INSERT_QUEUE);
}
resetModifyState();
postElementCollectionUpdate();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ private void saveCollection() {
sqlInsert.setParameter(parentId);
sqlInsert.setParameter(entry.getKey());
many.bindElementValue(sqlInsert, entry.getValue());
persister.addToFlushQueue(sqlInsert, transaction, 2);
persister.addToFlushQueue(sqlInsert, transaction, BatchControl.INSERT_QUEUE);
}
resetModifyState();
postElementCollectionUpdate();
Expand Down
26 changes: 25 additions & 1 deletion ebean-test/src/test/java/org/tests/m2m/TestM2MModifyTest.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package org.tests.m2m;

import io.ebean.xtest.BaseTestCase;
import io.ebean.DB;
import io.ebean.xtest.BaseTestCase;
import org.junit.jupiter.api.Test;
import org.tests.model.basic.MRole;
import org.tests.model.basic.MUser;

import java.util.ArrayList;
import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;
Expand Down Expand Up @@ -52,4 +53,27 @@ public void test() {
roles = u0.getRoles();
assertThat(roles).hasSize(1);
}

@Test
public void test1() {
List<MRole> roles = new ArrayList<>();
for (int i = 0; i < 56; i++) {
MRole r0 = new MRole("mrole" + i);
roles.add(r0);
}

DB.saveAll(roles);

MUser u0 = new MUser("usr0");
u0.getRoles().addAll(roles);

DB.save(u0);

u0 = DB.find(MUser.class, u0.getUserid());

u0.getRoles().clear();
u0.getRoles().addAll(roles);

DB.save(u0);
}
}

0 comments on commit ac1b307

Please sign in to comment.