Bug - OneToMany orphanRemoval = true, replace collection adding back original collection entry

- Adding back a bean from the original collection
- Expect that bean to exist in the final result but, it's missing

Fix here is in SaveManyBeans to add a insertAllChildren and use ebi.setNew(); for beans to force them to insert for this case.
This commit is contained in:
Rob Bygrave
2022-05-12 23:14:26 +12:00
parent 4b260483ce
commit 74174444bb
2 changed files with 57 additions and 1 deletions
@@ -35,6 +35,7 @@ public final class SaveManyBeans extends SaveManyBase {
private final boolean untouchedBeanCollection;
private final Collection<?> collection;
private int sortOrder;
private boolean insertAllChildren;
SaveManyBeans(DefaultPersister persister, boolean insertedParent, BeanPropertyAssocMany<?> many, EntityBean parentBean, PersistRequestBean<?> request) {
super(persister, insertedParent, many, parentBean, request);
@@ -176,8 +177,11 @@ public final class SaveManyBeans extends SaveManyBase {
skipSavingThisBean = false;
// set the parent bean to detailBean
many.setJoinValuesToChild(parentBean, detail, mapKeyValue);
} else if (insertAllChildren) {
ebi.setNew();
skipSavingThisBean = false;
many.setJoinValuesToChild(parentBean, detail, mapKeyValue);
} else {
// unmodified so skip depending on prop.isSaveRecurseSkippable();
skipSavingThisBean = saveRecurseSkippable;
}
}
@@ -342,6 +346,7 @@ public final class SaveManyBeans extends SaveManyBase {
if (!(value instanceof BeanCollection<?>)) {
if (!insertedParent && cascade && isChangedProperty()) {
persister.addToFlushQueue(many.deleteByParentId(request.beanId(), null), transaction, 0);
insertAllChildren = true;
}
} else {
BeanCollection<?> c = (BeanCollection<?>) value;
@@ -0,0 +1,51 @@
package org.tests.cascade;
import io.ebean.DB;
import io.ebean.xtest.BaseTestCase;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import static java.util.Objects.requireNonNull;
import static org.junit.jupiter.api.Assertions.assertEquals;
class TestOrphanCollectionReplacement extends BaseTestCase {
@Test
void replaceCollection_whenOrphan_expect_forcedInsert() {
long parentId;
{ // setup
List<COOneMany> children = new ArrayList<>();
children.add(new COOneMany("c0"));
children.add(new COOneMany("c1"));
COOne parent = new COOne("p0");
parent.setChildren(children);
DB.save(parent);
parentId = parent.getId();
}
{ // act
COOne fetchedParent = DB.find(COOne.class, parentId);
assert fetchedParent != null;
COOneMany role = new COOneMany("c2");
List<COOneMany> filtered = fetchedParent.getChildren().stream().filter(r -> "c0".equals(r.getName())).collect(Collectors.toList());
List<COOneMany> updatedRoles = new ArrayList<>();
updatedRoles.addAll(filtered);
updatedRoles.addAll(List.of(role));
fetchedParent.setChildren(updatedRoles);
DB.save(fetchedParent);
}
COOne fetchedUser2 = DB.find(COOne.class, parentId);
requireNonNull(fetchedUser2);
assertEquals(2, fetchedUser2.getChildren().size());
}
}