Removing elements with @OrderColumn with a tree depth > 1 doesn't work (#1988)

* ADD: failing testcase for orderColumn when tree depth > 1

* FIX: no update with @OrderColumn on treeDepth > 1 and avoid needless updates

* ADD: failing testcase for removing models in oneToMany relation with @OrderColumn

Signed-off-by: Jonas Pöhler (JPo) <jonas.poehler@foconis.de>

* ADD: failing test for faulty element reordering in a entityBean tree with version

Signed-off-by: Jonas Pöhler (JPo) <jonas.poehler@foconis.de>

* FIX: incorrect behaviour when reordering or removing elements from collection with @OrderColumn.

Signed-off-by: Jonas Pöhler (JPo) <jonas.poehler@foconis.de>
This commit is contained in:
Jonas Pöhler
2020-04-14 23:07:00 +12:00
committed by GitHub
parent 52735179d9
commit c9588586c9
8 changed files with 379 additions and 4 deletions
@@ -0,0 +1,118 @@
package org.tests.model.version;
import io.ebean.BaseTestCase;
import io.ebean.Ebean;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
public class TestVersionHierarchyModification extends BaseTestCase {
@Before
public void setup() {
final VersionParent parent = new VersionParent();
parent.setName("vParent");
final VersionChild child1 = new VersionChild();
child1.setName("vChild1");
parent.getChildren().add(child1);
final VersionToy toy11 = new VersionToy();
toy11.setName("vToy1.1");
child1.getToys().add(toy11);
final VersionToy toy12 = new VersionToy();
toy12.setName("vToy1.2");
child1.getToys().add(toy12);
final VersionChild child2 = new VersionChild();
child2.setName("vChild2");
parent.getChildren().add(child2);
final VersionToy toy21 = new VersionToy();
toy21.setName("vToy2.1");
child2.getToys().add(toy21);
final VersionToy toy22 = new VersionToy();
toy22.setName("vToy2.2");
child2.getToys().add(toy22);
Ebean.save(parent);
}
@After
public void cleanUp() {
Ebean.find(VersionParent.class).delete();
}
@Test
public void testMoveDown() {
VersionParent parent = Ebean.find(VersionParent.class).findOne();
assertThat(parent).isNotNull();
assertThat(parent.getChildren()).hasSize(2);
VersionChild firstChild = parent.getChildren().get(0);
VersionChild secondChild = parent.getChildren().get(1);
assertThat(firstChild.getToys()).hasSize(2);
assertThat(secondChild.getToys()).hasSize(2);
assertThat(firstChild.getToys()).extracting(VersionToy::getName).containsExactly("vToy1.1", "vToy1.2");
assertThat(secondChild.getToys()).extracting(VersionToy::getName).containsExactly("vToy2.1", "vToy2.2");
final VersionToy toyToMove = firstChild.getToys().get(0);
firstChild.getToys().remove(toyToMove);
toyToMove.setChild(secondChild);
secondChild.getToys().add(1, toyToMove);
Ebean.save(parent);
parent = Ebean.find(VersionParent.class).findOne();
assertThat(parent).isNotNull();
assertThat(parent.getChildren()).hasSize(2);
firstChild = parent.getChildren().get(0);
secondChild = parent.getChildren().get(1);
assertThat(firstChild.getToys()).hasSize(1);
assertThat(secondChild.getToys()).hasSize(3);
assertThat(firstChild.getToys()).extracting(VersionToy::getName).containsExactly("vToy1.2");
assertThat(secondChild.getToys()).extracting(VersionToy::getName).containsExactly("vToy2.1", "vToy1.1", "vToy2.2");
}
@Test
public void testMoveUp() {
VersionParent parent = Ebean.find(VersionParent.class).findOne();
assertThat(parent).isNotNull();
assertThat(parent.getChildren()).hasSize(2);
VersionChild firstChild = parent.getChildren().get(0);
VersionChild secondChild = parent.getChildren().get(1);
assertThat(firstChild.getToys()).hasSize(2);
assertThat(secondChild.getToys()).hasSize(2);
assertThat(firstChild.getToys()).extracting(VersionToy::getName).containsExactly("vToy1.1", "vToy1.2");
assertThat(secondChild.getToys()).extracting(VersionToy::getName).containsExactly("vToy2.1", "vToy2.2");
final VersionToy toyToMove = secondChild.getToys().get(0);
secondChild.getToys().remove(toyToMove);
toyToMove.setChild(firstChild);
firstChild.getToys().add(1, toyToMove);
Ebean.save(parent);
parent = Ebean.find(VersionParent.class).findOne();
assertThat(parent).isNotNull();
assertThat(parent.getChildren()).hasSize(2);
firstChild = parent.getChildren().get(0);
secondChild = parent.getChildren().get(1);
assertThat(secondChild.getToys()).hasSize(1);
assertThat(firstChild.getToys()).hasSize(3);
assertThat(secondChild.getToys()).extracting(VersionToy::getName).containsExactly("vToy2.2");
assertThat(firstChild.getToys()).extracting(VersionToy::getName).containsExactly("vToy1.1", "vToy2.1", "vToy1.2");
}
}
@@ -0,0 +1,70 @@
package org.tests.model.version;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OrderColumn;
import javax.persistence.Version;
import java.util.ArrayList;
import java.util.List;
@Entity
public class VersionChild {
@Id
Integer id;
String name;
@Version
Integer version;
@OneToMany(mappedBy = "child", cascade = CascadeType.ALL, orphanRemoval = true)
@OrderColumn(name = "position")
List<VersionToy> toys = new ArrayList<>();
@ManyToOne
VersionParent parent;
public Integer getId() {
return id;
}
public void setId(final Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
public Integer getVersion() {
return version;
}
public void setVersion(final Integer version) {
this.version = version;
}
public List<VersionToy> getToys() {
return toys;
}
public void setToys(final List<VersionToy> toys) {
this.toys = toys;
}
public VersionParent getParent() {
return parent;
}
public void setParent(final VersionParent parent) {
this.parent = parent;
}
}
@@ -0,0 +1,58 @@
package org.tests.model.version;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.OrderColumn;
import javax.persistence.Version;
import java.util.ArrayList;
import java.util.List;
@Entity
public class VersionParent {
@Id
Integer id;
@Version
Integer version;
String name;
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true)
@OrderColumn(name = "position")
List<VersionChild> children = new ArrayList<>();
public Integer getId() {
return id;
}
public void setId(final Integer id) {
this.id = id;
}
public Integer getVersion() {
return version;
}
public void setVersion(final Integer version) {
this.version = version;
}
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
public List<VersionChild> getChildren() {
return children;
}
public void setChildren(final List<VersionChild> children) {
this.children = children;
}
}
@@ -0,0 +1,53 @@
package org.tests.model.version;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Version;
@Entity
public class VersionToy {
@Id
Integer id;
String name;
@Version
Integer version;
@ManyToOne
VersionChild child;
public Integer getId() {
return id;
}
public void setId(final Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
public Integer getVersion() {
return version;
}
public void setVersion(final Integer version) {
this.version = version;
}
public VersionChild getChild() {
return child;
}
public void setChild(final VersionChild child) {
this.child = child;
}
}
@@ -107,4 +107,41 @@ public class TestOrderColumn extends TransactionalTestCase {
assertThat(sql.get(2)).contains("bind(tt32");
}
@Test
public void testRemoveElement() {
final OrderMaster master = new OrderMaster();
for (int i = 0; i < 5; i++) {
final OrderReferencedChild child = new OrderReferencedChild("p" + i);
child.setChildName("c" + i);
for (int j = 0; j < 3; j++) {
final OrderToy toy = new OrderToy("t" + i + j);
child.getToys().add(toy);
}
master.getChildren().add(child);
}
Ebean.save(master);
final OrderMaster result = Ebean.find(OrderMaster.class).findOne();
final List<OrderReferencedChild> children = result.getChildren();
assertThat(children).hasSize(5);
final OrderReferencedChild child = children.get(0);
child.getToys().remove(1);
LoggedSqlCollector.start();
Ebean.save(result);
final List<String> sql = LoggedSqlCollector.stop();
assertThat(sql).hasSize(4);
assertSql(sql.get(0)).contains("delete from order_toy where id=?");
assertSql(sql.get(2)).contains("update order_toy set sort_order=? where id=?");
assertSql(sql.get(3)).contains("bind(2,");
}
}